All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] xfs: add customizable default values for error configuration
@ 2017-08-31 14:15 Hou Tao
  2017-08-31 14:15 ` [PATCH 1/7] xfs: prepare for the customizable default values of " Hou Tao
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

Hi all,

This is the initial patchset based on feedbacks from the RFC patcheset [1].
Its main purpose is adding customizable default values for XFS error
configuration, so a default value can be configured for all XFS filesystems
at one time.

A sysfs tree is created under .../xfs/default_error and its hierarchies are
the same with the tree under .../fs/xfs/<dev>/error. The main change is the
implementation method of the default error configuration. In the RFC patchset,
a modify-and-notify method is used. Now, a distinct flag is kept for each
fs-specific error configuration. The flag denotes the error configuration has
a no-default value, and it will be set when a value of no-"default" is written
to the corresponding sysfs file, and will be cleared when a value of "default"
is wrote. These flags will checked by xfs_error_get_cfg() when returning an
error configuration to XFS error handler.

Other changes include adding an extra sysfs attribute named summary to assist
the test of error configuration ("default" vs no-"default") and updating the
documentation accordingly.

Thoughts, reviews, flames appreciated.

Tao

[1]: http://www.spinics.net/lists/linux-xfs/msg09362.html

Hou Tao (7):
  xfs: prepare for the customizable default values of error
    configuration
  xfs: add sysfs files for default values of error configuration
  xfs: make the default values of error configuration customizable and
    workable
  xfs: merge the initialization table into the default error
    configuration
  xfs: construct the values of error configuration for XFS error handler
  xfs: show the summary of error configurations for debugging purpose
  xfs: document the customizable default values of error configuration

 Documentation/filesystems/xfs.txt |  31 ++-
 fs/xfs/xfs_buf_item.c             |  23 +--
 fs/xfs/xfs_mount.c                |   9 +-
 fs/xfs/xfs_mount.h                |  45 ++++-
 fs/xfs/xfs_super.c                |  11 +-
 fs/xfs/xfs_sysfs.c                | 384 ++++++++++++++++++++++++++++----------
 fs/xfs/xfs_sysfs.h                |  11 +-
 7 files changed, 384 insertions(+), 130 deletions(-)

-- 
2.5.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/7] xfs: prepare for the customizable default values of error configuration
  2017-08-31 14:15 [PATCH 0/7] xfs: add customizable default values for error configuration Hou Tao
@ 2017-08-31 14:15 ` Hou Tao
  2017-08-31 14:15 ` [PATCH 2/7] xfs: add sysfs files for " Hou Tao
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

The refactoring includes the following changes:
* move error configuration related fields into a single struct
  xfs_error_obj, so it can be used on both the default erorr
  configuration and the fs-specific one
* move kobj out of xfs_error_cfg to make it small, so we can
  define it on stack and get the values by mixing the values
  from the default error configuration and the fs-specific one

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 fs/xfs/xfs_buf_item.c | 22 ++++++-------
 fs/xfs/xfs_mount.c    |  8 ++---
 fs/xfs/xfs_mount.h    | 23 +++++++++----
 fs/xfs/xfs_sysfs.c    | 91 ++++++++++++++++++++++++++++-----------------------
 fs/xfs/xfs_sysfs.h    |  8 +++--
 5 files changed, 87 insertions(+), 65 deletions(-)

diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 573fc72..186c5f5 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -1088,7 +1088,7 @@ xfs_buf_iodone_callback_error(
 	struct xfs_mount	*mp = lip->li_mountp;
 	static ulong		lasttime;
 	static xfs_buftarg_t	*lasttarg;
-	struct xfs_error_cfg	*cfg;
+	struct xfs_error_cfg	cfg;
 
 	/*
 	 * If we've already decided to shutdown the filesystem because of
@@ -1111,7 +1111,7 @@ xfs_buf_iodone_callback_error(
 	trace_xfs_buf_item_iodone_async(bp, _RET_IP_);
 	ASSERT(bp->b_iodone != NULL);
 
-	cfg = xfs_error_get_cfg(mp, XFS_ERR_METADATA, bp->b_error);
+	xfs_error_get_cfg(&mp->m_eobj, XFS_ERR_METADATA, bp->b_error, &cfg);
 
 	/*
 	 * If the write was asynchronous then no one will be looking for the
@@ -1124,7 +1124,7 @@ xfs_buf_iodone_callback_error(
 	     bp->b_last_error != bp->b_error) {
 		bp->b_flags |= (XBF_WRITE | XBF_DONE | XBF_WRITE_FAIL);
 		bp->b_last_error = bp->b_error;
-		if (cfg->retry_timeout != XFS_ERR_RETRY_FOREVER &&
+		if (cfg.retry_timeout != XFS_ERR_RETRY_FOREVER &&
 		    !bp->b_first_retry_time)
 			bp->b_first_retry_time = jiffies;
 
@@ -1137,16 +1137,16 @@ xfs_buf_iodone_callback_error(
 	 * Repeated failure on an async write. Take action according to the
 	 * error configuration we have been set up to use.
 	 */
-
-	if (cfg->max_retries != XFS_ERR_RETRY_FOREVER &&
-	    ++bp->b_retries > cfg->max_retries)
-			goto permanent_error;
-	if (cfg->retry_timeout != XFS_ERR_RETRY_FOREVER &&
-	    time_after(jiffies, cfg->retry_timeout + bp->b_first_retry_time))
-			goto permanent_error;
+	if (cfg.max_retries != XFS_ERR_RETRY_FOREVER &&
+			++bp->b_retries > cfg.max_retries)
+		goto permanent_error;
+	if (cfg.retry_timeout != XFS_ERR_RETRY_FOREVER &&
+			time_after(jiffies,
+				cfg.retry_timeout + bp->b_first_retry_time))
+		goto permanent_error;
 
 	/* At unmount we may treat errors differently */
-	if ((mp->m_flags & XFS_MOUNT_UNMOUNTING) && mp->m_fail_unmount)
+	if ((mp->m_flags & XFS_MOUNT_UNMOUNTING) && mp->m_eobj.fail_unmount)
 		goto permanent_error;
 
 	/*
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index ea7d4b4..3970066 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -704,7 +704,7 @@ xfs_mountfs(
 	xfs_set_maxicount(mp);
 
 	/* enable fail_at_unmount as default */
-	mp->m_fail_unmount = 1;
+	mp->m_eobj.fail_unmount = true;
 
 	error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype, NULL, mp->m_fsname);
 	if (error)
@@ -715,7 +715,7 @@ xfs_mountfs(
 	if (error)
 		goto out_remove_sysfs;
 
-	error = xfs_error_sysfs_init(mp);
+	error = xfs_error_sysfs_init(&mp->m_eobj, &mp->m_kobj, "error");
 	if (error)
 		goto out_del_stats;
 
@@ -1042,7 +1042,7 @@ xfs_mountfs(
  out_remove_errortag:
 	xfs_errortag_del(mp);
  out_remove_error_sysfs:
-	xfs_error_sysfs_del(mp);
+	xfs_error_sysfs_del(&mp->m_eobj);
  out_del_stats:
 	xfs_sysfs_del(&mp->m_stats.xs_kobj);
  out_remove_sysfs:
@@ -1149,7 +1149,7 @@ xfs_unmountfs(
 	xfs_free_perag(mp);
 
 	xfs_errortag_del(mp);
-	xfs_error_sysfs_del(mp);
+	xfs_error_sysfs_del(&mp->m_eobj);
 	xfs_sysfs_del(&mp->m_stats.xs_kobj);
 	xfs_sysfs_del(&mp->m_kobj);
 }
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index e0792d0..15e35f7 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -64,11 +64,23 @@ enum {
  * signed lets us store the special "-1" value, meaning retry forever.
  */
 struct xfs_error_cfg {
-	struct xfs_kobj	kobj;
 	int		max_retries;
 	long		retry_timeout;	/* in jiffies, -1 = infinite */
 };
 
+struct xfs_error_cfg_kobj {
+	struct xfs_kobj kobj;
+	struct xfs_error_cfg cfg;
+};
+
+struct xfs_error_obj {
+	struct xfs_kobj kobj;
+	struct xfs_kobj meta_kobj;
+	struct xfs_error_cfg_kobj
+		cfg_kobj[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
+	bool fail_unmount;
+};
+
 typedef struct xfs_mount {
 	struct super_block	*m_super;
 	xfs_tid_t		m_tid;		/* next unused tid for fs */
@@ -171,9 +183,7 @@ typedef struct xfs_mount {
 	int64_t			m_low_space[XFS_LOWSP_MAX];
 						/* low free space thresholds */
 	struct xfs_kobj		m_kobj;
-	struct xfs_kobj		m_error_kobj;
-	struct xfs_kobj		m_error_meta_kobj;
-	struct xfs_error_cfg	m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
+	struct xfs_error_obj	m_eobj;
 	struct xstats		m_stats;	/* per-fs stats */
 
 	struct workqueue_struct *m_buf_workqueue;
@@ -196,7 +206,6 @@ typedef struct xfs_mount {
 	 */
 	uint32_t		m_generation;
 
-	bool			m_fail_unmount;
 #ifdef DEBUG
 	/*
 	 * Frequency with which errors are injected.  Replaces xfs_etest; the
@@ -443,7 +452,7 @@ extern void	xfs_set_low_space_thresholds(struct xfs_mount *);
 int	xfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb,
 			xfs_off_t count_fsb);
 
-struct xfs_error_cfg * xfs_error_get_cfg(struct xfs_mount *mp,
-		int error_class, int error);
+void xfs_error_get_cfg(struct xfs_error_obj *eobj,
+		int error_class, int error, struct xfs_error_cfg *cfg);
 
 #endif	/* __XFS_MOUNT_H__ */
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index 8b2ccc2..966cf3f 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -47,7 +47,7 @@ to_attr(struct attribute *attr)
 #define XFS_SYSFS_ATTR_WO(name) \
 	static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name)
 
-#define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr
+#define ATTR_LIST(name) (&xfs_sysfs_attr_##name.attr)
 
 STATIC ssize_t
 xfs_sysfs_object_show(
@@ -333,14 +333,17 @@ static inline struct xfs_error_cfg *
 to_error_cfg(struct kobject *kobject)
 {
 	struct xfs_kobj *kobj = to_kobj(kobject);
-	return container_of(kobj, struct xfs_error_cfg, kobj);
+	struct xfs_error_cfg_kobj *cfg_kobj =
+		container_of(kobj, struct xfs_error_cfg_kobj, kobj);
+
+	return &cfg_kobj->cfg;
 }
 
-static inline struct xfs_mount *
+static inline struct xfs_error_obj *
 err_to_mp(struct kobject *kobject)
 {
 	struct xfs_kobj *kobj = to_kobj(kobject);
-	return container_of(kobj, struct xfs_mount, m_error_kobj);
+	return container_of(kobj, struct xfs_error_obj, kobj);
 }
 
 static ssize_t
@@ -433,9 +436,9 @@ fail_at_unmount_show(
 	struct kobject	*kobject,
 	char		*buf)
 {
-	struct xfs_mount	*mp = err_to_mp(kobject);
+	struct xfs_error_obj *eobj = err_to_mp(kobject);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount);
+	return snprintf(buf, PAGE_SIZE, "%d\n", eobj->fail_unmount);
 }
 
 static ssize_t
@@ -444,7 +447,7 @@ fail_at_unmount_store(
 	const char	*buf,
 	size_t		count)
 {
-	struct xfs_mount	*mp = err_to_mp(kobject);
+	struct xfs_error_obj *eobj = err_to_mp(kobject);
 	int		ret;
 	int		val;
 
@@ -455,7 +458,7 @@ fail_at_unmount_store(
 	if (val < 0 || val > 1)
 		return -EINVAL;
 
-	mp->m_fail_unmount = val;
+	eobj->fail_unmount = val;
 	return count;
 }
 XFS_SYSFS_ATTR_RW(fail_at_unmount);
@@ -511,30 +514,33 @@ static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
 
 static int
 xfs_error_sysfs_init_class(
-	struct xfs_mount	*mp,
+	struct xfs_error_obj	*eobj,
 	int			class,
 	const char		*parent_name,
-	struct xfs_kobj		*parent_kobj,
+	struct xfs_kobj	*parent_kobj,
 	const struct xfs_error_init init[])
 {
-	struct xfs_error_cfg	*cfg;
+	struct xfs_error_cfg_kobj *cfg_kobj;
 	int			error;
 	int			i;
 
 	ASSERT(class < XFS_ERR_CLASS_MAX);
 
 	error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,
-				&mp->m_error_kobj, parent_name);
+				&eobj->kobj, parent_name);
 	if (error)
 		return error;
 
 	for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
-		cfg = &mp->m_error_cfg[class][i];
-		error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,
+		struct xfs_error_cfg *cfg;
+
+		cfg_kobj = &eobj->cfg_kobj[class][i];
+		error = xfs_sysfs_init(&cfg_kobj->kobj, &xfs_error_cfg_ktype,
 					parent_kobj, init[i].name);
 		if (error)
 			goto out_error;
 
+		cfg = &cfg_kobj->cfg;
 		cfg->max_retries = init[i].max_retries;
 		if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
 			cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
@@ -542,13 +548,14 @@ xfs_error_sysfs_init_class(
 			cfg->retry_timeout = msecs_to_jiffies(
 					init[i].retry_timeout * MSEC_PER_SEC);
 	}
+
 	return 0;
 
 out_error:
 	/* unwind the entries that succeeded */
 	for (i--; i >= 0; i--) {
-		cfg = &mp->m_error_cfg[class][i];
-		xfs_sysfs_del(&cfg->kobj);
+		cfg_kobj = &eobj->cfg_kobj[class][i];
+		xfs_sysfs_del(&cfg_kobj->kobj);
 	}
 	xfs_sysfs_del(parent_kobj);
 	return error;
@@ -556,25 +563,26 @@ xfs_error_sysfs_init_class(
 
 int
 xfs_error_sysfs_init(
-	struct xfs_mount	*mp)
+	struct xfs_error_obj	*eobj,
+	struct xfs_kobj	*parent,
+	const char	*name)
 {
 	int			error;
 
 	/* .../xfs/<dev>/error/ */
-	error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
-				&mp->m_kobj, "error");
+	error = xfs_sysfs_init(&eobj->kobj, &xfs_error_ktype,
+				parent, name);
 	if (error)
 		return error;
 
-	error = sysfs_create_file(&mp->m_error_kobj.kobject,
-				  ATTR_LIST(fail_at_unmount));
-
+	error = sysfs_create_file(&eobj->kobj.kobject,
+					ATTR_LIST(fail_at_unmount));
 	if (error)
 		goto out_error;
 
 	/* .../xfs/<dev>/error/metadata/ */
-	error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,
-				"metadata", &mp->m_error_meta_kobj,
+	error = xfs_error_sysfs_init_class(eobj, XFS_ERR_METADATA,
+				"metadata", &eobj->meta_kobj,
 				xfs_error_meta_init);
 	if (error)
 		goto out_error;
@@ -582,53 +590,54 @@ xfs_error_sysfs_init(
 	return 0;
 
 out_error:
-	xfs_sysfs_del(&mp->m_error_kobj);
+	xfs_sysfs_del(&eobj->kobj);
 	return error;
 }
 
 void
 xfs_error_sysfs_del(
-	struct xfs_mount	*mp)
+	struct xfs_error_obj	*eobj)
 {
-	struct xfs_error_cfg	*cfg;
+	struct xfs_kobj *kobj;
 	int			i, j;
 
 	for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {
 		for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {
-			cfg = &mp->m_error_cfg[i][j];
-
-			xfs_sysfs_del(&cfg->kobj);
+			kobj = &eobj->cfg_kobj[i][j].kobj;
+			xfs_sysfs_del(kobj);
 		}
 	}
-	xfs_sysfs_del(&mp->m_error_meta_kobj);
-	xfs_sysfs_del(&mp->m_error_kobj);
+
+	xfs_sysfs_del(&eobj->meta_kobj);
+	xfs_sysfs_del(&eobj->kobj);
 }
 
-struct xfs_error_cfg *
+void
 xfs_error_get_cfg(
-	struct xfs_mount	*mp,
+	struct xfs_error_obj	*eobj,
 	int			error_class,
-	int			error)
+	int			error,
+	struct xfs_error_cfg	*cfg)
 {
-	struct xfs_error_cfg	*cfg;
+	int idx;
 
 	if (error < 0)
 		error = -error;
 
 	switch (error) {
 	case EIO:
-		cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];
+		idx = XFS_ERR_EIO;
 		break;
 	case ENOSPC:
-		cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];
+		idx = XFS_ERR_ENOSPC;
 		break;
 	case ENODEV:
-		cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];
+		idx = XFS_ERR_ENODEV;
 		break;
 	default:
-		cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];
+		idx = XFS_ERR_DEFAULT;
 		break;
 	}
 
-	return cfg;
+	*cfg = eobj->cfg_kobj[error_class][idx].cfg;
 }
diff --git a/fs/xfs/xfs_sysfs.h b/fs/xfs/xfs_sysfs.h
index d046371..a0e4c17 100644
--- a/fs/xfs/xfs_sysfs.h
+++ b/fs/xfs/xfs_sysfs.h
@@ -24,6 +24,9 @@ extern struct kobj_type xfs_dbg_ktype;	/* debug */
 extern struct kobj_type xfs_log_ktype;	/* xlog */
 extern struct kobj_type xfs_stats_ktype;	/* stats */
 
+/* for the declarations of xfs_error_sysfs_init/del */
+struct xfs_error_obj;
+
 static inline struct xfs_kobj *
 to_kobj(struct kobject *kobject)
 {
@@ -58,7 +61,8 @@ xfs_sysfs_del(
 	wait_for_completion(&kobj->complete);
 }
 
-int	xfs_error_sysfs_init(struct xfs_mount *mp);
-void	xfs_error_sysfs_del(struct xfs_mount *mp);
+int xfs_error_sysfs_init(struct xfs_error_obj *eobj,
+		struct xfs_kobj *parent, const char *name);
+void xfs_error_sysfs_del(struct xfs_error_obj *eobj);
 
 #endif	/* __XFS_SYSFS_H__ */
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/7] xfs: add sysfs files for default values of error configuration
  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 ` Hou Tao
  2017-08-31 14:15 ` [PATCH 3/7] xfs: make the default values of error configuration customizable and workable Hou Tao
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

Both the hierarchies and the names are the same with the sysfs tree
of the filesystem-specific error configuration. The only difference
is the root of error configuration sysfs tree: for the default error
configuration it is ".../xfs/default_error/" instead of
".../xfs/<dev_name>/error/".

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 fs/xfs/xfs_super.c | 11 +++++++++--
 fs/xfs/xfs_sysfs.c | 22 ++++++++++++++++++++--
 fs/xfs/xfs_sysfs.h |  3 +++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 38aaacd..3a3812b4 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -2043,11 +2043,15 @@ init_xfs_fs(void)
 	if (error)
 		goto out_free_stats;
 
+	error = xfs_dft_error_sysfs_init(xfs_kset);
+	if (error)
+		goto out_remove_stats_kobj;
+
 #ifdef DEBUG
 	xfs_dbg_kobj.kobject.kset = xfs_kset;
 	error = xfs_sysfs_init(&xfs_dbg_kobj, &xfs_dbg_ktype, NULL, "debug");
 	if (error)
-		goto out_remove_stats_kobj;
+		goto out_remove_dft_error_sysfs;
 #endif
 
 	error = xfs_qm_init();
@@ -2064,8 +2068,10 @@ init_xfs_fs(void)
  out_remove_dbg_kobj:
 #ifdef DEBUG
 	xfs_sysfs_del(&xfs_dbg_kobj);
- out_remove_stats_kobj:
+ out_remove_dft_error_sysfs:
 #endif
+	xfs_dft_error_sysfs_del();
+ out_remove_stats_kobj:
 	xfs_sysfs_del(&xfsstats.xs_kobj);
  out_free_stats:
 	free_percpu(xfsstats.xs_stats);
@@ -2095,6 +2101,7 @@ exit_xfs_fs(void)
 #ifdef DEBUG
 	xfs_sysfs_del(&xfs_dbg_kobj);
 #endif
+	xfs_dft_error_sysfs_del();
 	xfs_sysfs_del(&xfsstats.xs_kobj);
 	free_percpu(xfsstats.xs_stats);
 	kset_unregister(xfs_kset);
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index 966cf3f..4a19fad 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -49,6 +49,8 @@ to_attr(struct attribute *attr)
 
 #define ATTR_LIST(name) (&xfs_sysfs_attr_##name.attr)
 
+static struct xfs_error_obj xfs_dft_eobj;
+
 STATIC ssize_t
 xfs_sysfs_object_show(
 	struct kobject		*kobject,
@@ -569,7 +571,7 @@ xfs_error_sysfs_init(
 {
 	int			error;
 
-	/* .../xfs/<dev>/error/ */
+	/* .../xfs/default_error/ or .../xfs/<dev>/error/ */
 	error = xfs_sysfs_init(&eobj->kobj, &xfs_error_ktype,
 				parent, name);
 	if (error)
@@ -580,7 +582,7 @@ xfs_error_sysfs_init(
 	if (error)
 		goto out_error;
 
-	/* .../xfs/<dev>/error/metadata/ */
+	/* .../xfs/error/metadata/ or .../xfs/<dev>/error/metadata/ */
 	error = xfs_error_sysfs_init_class(eobj, XFS_ERR_METADATA,
 				"metadata", &eobj->meta_kobj,
 				xfs_error_meta_init);
@@ -612,6 +614,22 @@ xfs_error_sysfs_del(
 	xfs_sysfs_del(&eobj->kobj);
 }
 
+int
+xfs_dft_error_sysfs_init(
+	struct kset *xfs_kset)
+{
+	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");
+}
+
+void
+xfs_dft_error_sysfs_del(void)
+{
+	xfs_error_sysfs_del(&xfs_dft_eobj);
+}
+
 void
 xfs_error_get_cfg(
 	struct xfs_error_obj	*eobj,
diff --git a/fs/xfs/xfs_sysfs.h b/fs/xfs/xfs_sysfs.h
index a0e4c17..90970c6 100644
--- a/fs/xfs/xfs_sysfs.h
+++ b/fs/xfs/xfs_sysfs.h
@@ -61,6 +61,9 @@ xfs_sysfs_del(
 	wait_for_completion(&kobj->complete);
 }
 
+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);
 void xfs_error_sysfs_del(struct xfs_error_obj *eobj);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/7] xfs: make the default values of error configuration customizable and workable
  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
  2017-08-31 14:15 ` [PATCH 4/7] xfs: merge the initialization table into the default error configuration Hou Tao
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

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


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/7] xfs: merge the initialization table into the default error configuration
  2017-08-31 14:15 [PATCH 0/7] xfs: add customizable default values for error configuration Hou Tao
                   ` (2 preceding siblings ...)
  2017-08-31 14:15 ` [PATCH 3/7] xfs: make the default values of error configuration customizable and workable Hou Tao
@ 2017-08-31 14:15 ` Hou Tao
  2017-08-31 14:15 ` [PATCH 5/7] xfs: construct the values of error configuration for XFS error handler Hou Tao
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

There is no need to save the initial default values in two difference
places: the initialization table and the default error configuration,
so merge them.

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 fs/xfs/xfs_mount.c |  3 ---
 fs/xfs/xfs_sysfs.c | 77 +++++++++++++++++++++++-------------------------------
 2 files changed, 32 insertions(+), 48 deletions(-)

diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 19f729e..bf56d97 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -703,9 +703,6 @@ xfs_mountfs(
 
 	xfs_set_maxicount(mp);
 
-	/* enable fail_at_unmount as default */
-	mp->m_eobj.fail_unmount = true;
-
 	error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype, NULL, mp->m_fsname);
 	if (error)
 		goto out;
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index 64f33b1..c623d92 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -52,6 +52,9 @@ to_attr(struct attribute *attr)
 
 #define ATTR_LIST(name) (&xfs_sysfs_attr_##name.attr)
 
+static const char *xfs_error_meta_name[XFS_ERR_ERRNO_MAX] = {
+	"default", "EIO", "ENOSPC", "ENODEV",
+};
 static struct xfs_error_obj xfs_dft_eobj;
 
 STATIC ssize_t
@@ -565,44 +568,13 @@ static struct kobj_type xfs_error_ktype = {
 	.sysfs_ops = &xfs_sysfs_ops,
 };
 
-/*
- * Error initialization tables. These need to be ordered in the same
- * order as the enums used to index the array. All class init tables need to
- * define a "default" behaviour as the first entry, all other entries can be
- * empty.
- */
-struct xfs_error_init {
-	char		*name;
-	int		max_retries;
-	int		retry_timeout;	/* in seconds */
-};
-
-static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
-	{ .name = "default",
-	  .max_retries = XFS_ERR_RETRY_FOREVER,
-	  .retry_timeout = XFS_ERR_RETRY_FOREVER,
-	},
-	{ .name = "EIO",
-	  .max_retries = XFS_ERR_RETRY_FOREVER,
-	  .retry_timeout = XFS_ERR_RETRY_FOREVER,
-	},
-	{ .name = "ENOSPC",
-	  .max_retries = XFS_ERR_RETRY_FOREVER,
-	  .retry_timeout = XFS_ERR_RETRY_FOREVER,
-	},
-	{ .name = "ENODEV",
-	  .max_retries = 0,	/* We can't recover from devices disappearing */
-	  .retry_timeout = 0,
-	},
-};
-
 static int
 xfs_error_sysfs_init_class(
 	struct xfs_error_obj	*eobj,
 	int			class,
 	const char		*parent_name,
 	struct xfs_kobj	*parent_kobj,
-	const struct xfs_error_init init[])
+	const char	*name[])
 {
 	struct xfs_error_cfg_kobj *cfg_kobj;
 	int			error;
@@ -616,23 +588,13 @@ xfs_error_sysfs_init_class(
 		return error;
 
 	for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
-		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);
+					parent_kobj, name[i]);
 		if (error)
 			goto out_error;
-
-		cfg = &cfg_kobj->cfg;
-		cfg->max_retries = init[i].max_retries;
-		if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
-			cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
-		else
-			cfg->retry_timeout = msecs_to_jiffies(
-					init[i].retry_timeout * MSEC_PER_SEC);
 	}
 
 	return 0;
@@ -672,7 +634,7 @@ xfs_error_sysfs_init(
 	/* .../xfs/error/metadata/ or .../xfs/<dev>/error/metadata/ */
 	error = xfs_error_sysfs_init_class(eobj, XFS_ERR_METADATA,
 				"metadata", &eobj->meta_kobj,
-				xfs_error_meta_init);
+				xfs_error_meta_name);
 	if (error)
 		goto out_error;
 
@@ -701,12 +663,37 @@ xfs_error_sysfs_del(
 	xfs_sysfs_del(&eobj->kobj);
 }
 
+static void
+xfs_dft_error_cfg_init(
+	struct xfs_error_obj *eobj)
+{
+	int class = XFS_ERR_METADATA;
+	int i;
+	struct xfs_error_cfg *cfg;
+
+	/* enable fail_unmount as default */
+	eobj->fail_unmount = true;
+
+	for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
+		cfg = &eobj->cfg_kobj[class][i].cfg;
+
+		cfg->max_retries = XFS_ERR_RETRY_FOREVER;
+		cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
+	}
+
+	/* We can't recover from devices disappearing */
+	cfg = &eobj->cfg_kobj[class][XFS_ERR_ENODEV].cfg;
+	cfg->max_retries = 0;
+	cfg->retry_timeout = 0;
+}
+
 int
 xfs_dft_error_sysfs_init(
 	struct kset *xfs_kset)
 {
 	xfs_dft_eobj.kobj.kobject.kset = xfs_kset;
-	xfs_dft_eobj.fail_unmount = true;
+
+	xfs_dft_error_cfg_init(&xfs_dft_eobj);
 
 	return xfs_error_sysfs_init(&xfs_dft_eobj, NULL, "default_error",
 			BIT(XFS_ERR_CFG_BIT_ALWAYS_PRIV));
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/7] xfs: construct the values of error configuration for XFS error handler
  2017-08-31 14:15 [PATCH 0/7] xfs: add customizable default values for error configuration Hou Tao
                   ` (3 preceding siblings ...)
  2017-08-31 14:15 ` [PATCH 4/7] xfs: merge the initialization table into the default error configuration Hou Tao
@ 2017-08-31 14:15 ` 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
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

When a corresponding XFS_ERR_CFG_BIT_* bit had been set on the error
configuration, the value of the fs-specific error configuration will
be returned, else the value of the default error configuration will
be used.

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

diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 186c5f5..4f9fd50 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -1146,7 +1146,8 @@ xfs_buf_iodone_callback_error(
 		goto permanent_error;
 
 	/* At unmount we may treat errors differently */
-	if ((mp->m_flags & XFS_MOUNT_UNMOUNTING) && mp->m_eobj.fail_unmount)
+	if ((mp->m_flags & XFS_MOUNT_UNMOUNTING) &&
+			xfs_fail_at_unmount(&mp->m_eobj))
 		goto permanent_error;
 
 	/*
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 906c3a4..ceed665 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -475,5 +475,6 @@ int	xfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb,
 
 void xfs_error_get_cfg(struct xfs_error_obj *eobj,
 		int error_class, int error, struct xfs_error_cfg *cfg);
+bool xfs_fail_at_unmount(struct xfs_error_obj *eobj);
 
 #endif	/* __XFS_MOUNT_H__ */
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index c623d92..cd7dfca 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -713,6 +713,7 @@ xfs_error_get_cfg(
 	struct xfs_error_cfg	*cfg)
 {
 	int idx;
+	struct xfs_error_cfg_kobj *kobj;
 
 	if (error < 0)
 		error = -error;
@@ -732,5 +733,21 @@ xfs_error_get_cfg(
 		break;
 	}
 
-	*cfg = eobj->cfg_kobj[error_class][idx].cfg;
+	*cfg = xfs_dft_eobj.cfg_kobj[error_class][idx].cfg;
+
+	kobj = &eobj->cfg_kobj[error_class][idx];
+	if (test_bit(XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES, &kobj->flags))
+		cfg->max_retries = kobj->cfg.max_retries;
+	if (test_bit(XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT, &kobj->flags))
+		cfg->retry_timeout = kobj->cfg.retry_timeout;
+}
+
+bool
+xfs_fail_at_unmount(
+	struct xfs_error_obj	*eobj)
+{
+	if (!test_bit(XFS_ERR_CFG_BIT_PRIV_FAIL_UNMOUNT, &eobj->flags))
+		return xfs_dft_eobj.fail_unmount;
+	else
+		return eobj->fail_unmount;
 }
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6/7] xfs: show the summary of error configurations for debugging purpose
  2017-08-31 14:15 [PATCH 0/7] xfs: add customizable default values for error configuration Hou Tao
                   ` (4 preceding siblings ...)
  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 ` Hou Tao
  2017-08-31 14:15 ` [PATCH 7/7] xfs: document the customizable default values of error configuration Hou Tao
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

When the value of an error configuration is "default", the actual
value used by XFS error handler is decided by the corresponding
default error configuration. To ensure they are the same, add
a sysfs file named "summary" to display the actual used values.

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 fs/xfs/xfs_sysfs.c | 115 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 89 insertions(+), 26 deletions(-)

diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index cd7dfca..0af5e56 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -30,6 +30,9 @@
 #define XFS_ERR_CFG_DEFAULT_VALUE "default"
 #define XFS_ERR_CFG_DEFAULT_VALUE_LEN 7
 
+static void _xfs_error_get_cfg(struct xfs_error_obj *eobj, int error_class,
+		int error_idx, struct xfs_error_cfg *cfg);
+
 struct xfs_sysfs_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct kobject *kobject, char *buf);
@@ -381,26 +384,33 @@ is_value_of_dft_error_cfg(
 			  buf[XFS_ERR_CFG_DEFAULT_VALUE_LEN + 1] == '\0')));
 }
 
+static int
+to_max_retries_show_fmt(
+	int max_retries)
+{
+	int		retries;
+
+	if (max_retries == XFS_ERR_RETRY_FOREVER)
+		retries = -1;
+	else
+		retries = max_retries;
+
+	return retries;
+}
+
 static ssize_t
 max_retries_show(
 	struct kobject	*kobject,
 	char		*buf)
 {
-	int		retries;
 	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
-		retries = cfg->max_retries;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", retries);
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			to_max_retries_show_fmt(cfg_kobj->cfg.max_retries));
 }
 
 static ssize_t
@@ -441,26 +451,33 @@ max_retries_store(
 }
 XFS_SYSFS_ATTR_RW(max_retries);
 
+static int
+to_retry_timeout_show_fmt(
+	long retry_timeout)
+{
+	int		timeout;
+
+	if (retry_timeout == XFS_ERR_RETRY_FOREVER)
+		timeout = -1;
+	else
+		timeout = jiffies_to_msecs(retry_timeout) / MSEC_PER_SEC;
+
+	return timeout;
+}
+
 static ssize_t
 retry_timeout_seconds_show(
 	struct kobject	*kobject,
 	char		*buf)
 {
-	int		timeout;
 	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
-		timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", timeout);
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			to_retry_timeout_show_fmt(cfg_kobj->cfg.retry_timeout));
 }
 
 static ssize_t
@@ -550,6 +567,35 @@ fail_at_unmount_store(
 }
 XFS_SYSFS_ATTR_RW(fail_at_unmount);
 
+#ifdef DEBUG
+static ssize_t
+summary_show(
+	struct kobject	*kobject,
+	char		*buf)
+{
+	struct xfs_error_obj *eobj = err_to_mp(kobject);
+	int len = PAGE_SIZE;
+	int used = 0;
+	int i;
+	struct xfs_error_cfg cfg;
+
+	used += snprintf(buf + used, len - used, "fail_at_unmount: %d\n",
+			xfs_fail_at_unmount(eobj));
+	for (i = 0; used < len && i < XFS_ERR_ERRNO_MAX; i++) {
+		_xfs_error_get_cfg(eobj, XFS_ERR_METADATA, i, &cfg);
+
+		used += snprintf(buf + used, len - used,
+				"metadata %s: retries %d timeout %d\n",
+				xfs_error_meta_name[i],
+				to_max_retries_show_fmt(cfg.max_retries),
+				to_retry_timeout_show_fmt(cfg.retry_timeout));
+	}
+
+	return used;
+}
+XFS_SYSFS_ATTR_RO(summary);
+#endif /* DEBUG */
+
 static struct attribute *xfs_error_attrs[] = {
 	ATTR_LIST(max_retries),
 	ATTR_LIST(retry_timeout_seconds),
@@ -631,6 +677,12 @@ xfs_error_sysfs_init(
 	if (error)
 		goto out_error;
 
+#ifdef DEBUG
+	error = sysfs_create_file(&eobj->kobj.kobject, ATTR_LIST(summary));
+	if (error)
+		goto out_error;
+#endif
+
 	/* .../xfs/error/metadata/ or .../xfs/<dev>/error/metadata/ */
 	error = xfs_error_sysfs_init_class(eobj, XFS_ERR_METADATA,
 				"metadata", &eobj->meta_kobj,
@@ -706,6 +758,24 @@ xfs_dft_error_sysfs_del(void)
 }
 
 void
+_xfs_error_get_cfg(
+	struct xfs_error_obj	*eobj,
+	int	error_class,
+	int	error_idx,
+	struct xfs_error_cfg *cfg)
+{
+	struct xfs_error_cfg_kobj *kobj;
+
+	*cfg = xfs_dft_eobj.cfg_kobj[error_class][error_idx].cfg;
+
+	kobj = &eobj->cfg_kobj[error_class][error_idx];
+	if (test_bit(XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES, &kobj->flags))
+		cfg->max_retries = kobj->cfg.max_retries;
+	if (test_bit(XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT, &kobj->flags))
+		cfg->retry_timeout = kobj->cfg.retry_timeout;
+}
+
+void
 xfs_error_get_cfg(
 	struct xfs_error_obj	*eobj,
 	int			error_class,
@@ -713,7 +783,6 @@ xfs_error_get_cfg(
 	struct xfs_error_cfg	*cfg)
 {
 	int idx;
-	struct xfs_error_cfg_kobj *kobj;
 
 	if (error < 0)
 		error = -error;
@@ -733,13 +802,7 @@ xfs_error_get_cfg(
 		break;
 	}
 
-	*cfg = xfs_dft_eobj.cfg_kobj[error_class][idx].cfg;
-
-	kobj = &eobj->cfg_kobj[error_class][idx];
-	if (test_bit(XFS_ERR_CFG_BIT_PRIV_MAX_RETRIES, &kobj->flags))
-		cfg->max_retries = kobj->cfg.max_retries;
-	if (test_bit(XFS_ERR_CFG_BIT_PRIV_RETRY_TIMEOUT, &kobj->flags))
-		cfg->retry_timeout = kobj->cfg.retry_timeout;
+	_xfs_error_get_cfg(eobj, error_class, idx, cfg);
 }
 
 bool
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 7/7] xfs: document the customizable default values of error configuration
  2017-08-31 14:15 [PATCH 0/7] xfs: add customizable default values for error configuration Hou Tao
                   ` (5 preceding siblings ...)
  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 ` Hou Tao
  6 siblings, 0 replies; 8+ messages in thread
From: Hou Tao @ 2017-08-31 14:15 UTC (permalink / raw)
  To: linux-xfs; +Cc: darrick.wong, david, cmaiolino

Mainly the sysfs paths of the default values and the difference between
the default errror configuration and the fs-specific one.

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 Documentation/filesystems/xfs.txt | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
index 3b9b5c1..0be68fc 100644
--- a/Documentation/filesystems/xfs.txt
+++ b/Documentation/filesystems/xfs.txt
@@ -397,12 +397,25 @@ Where:
   <error>
 	The individual error handler configurations.
 
+For the convenience of error configuration, there are also configuration files
+used for the default values of error configuration of all mounted filesystem:
+
+  /sys/fs/xfs/default_error/<class>/<error>/
+
+There is only one difference between the error configuration options under
+these two sysfs trees: the options under <dev>/error/ can have a value of
+"default", and the options under default_error/ can not.
 
 Each filesystem has "global" error configuration options defined in their top
 level directory:
 
   /sys/fs/xfs/<dev>/error/
 
+For the default values of the "global" error configuration options, the
+directory is:
+
+  /sys/fs/xfs/default_error/
+
   fail_at_unmount		(Min:  0  Default:  1  Max: 1)
 	Defines the filesystem error behavior at unmount time.
 
@@ -417,6 +430,9 @@ level directory:
 	filesystem from ever unmounting fully in the case of "retry forever"
 	handler configurations.
 
+	If set to "default", the behavior will be decided by the value of
+	/sys/fs/xfs/default_error/fail_at_unmount.
+
 	Note: there is no guarantee that fail_at_unmount can be set whilst an
 	unmount is in progress. It is possible that the sysfs entries are
 	removed by the unmounting filesystem before a "retry forever" error
@@ -427,12 +443,17 @@ level directory:
 Each filesystem has specific error class handlers that define the error
 propagation behaviour for specific errors. There is also a "default" error
 handler defined, which defines the behaviour for all errors that don't have
-specific handlers defined. Where multiple retry constraints are configuredi for
+specific handlers defined. Where multiple retry constraints are configured for
 a single error, the first retry configuration that expires will cause the error
 to be propagated. The handler configurations are found in the directory:
 
   /sys/fs/xfs/<dev>/error/<class>/<error>/
 
+There is also a corresponding directory for the default values of these
+handler configuration:
+
+  /sys/fs/xfs/default_error/<class>/<error>/
+
   max_retries			(Min: -1  Default: Varies  Max: INTMAX)
 	Defines the allowed number of retries of a specific error before
 	the filesystem will propagate the error. The retry count for a given
@@ -448,6 +469,10 @@ to be propagated. The handler configurations are found in the directory:
 	Setting the value to "N" (where 0 < N < Max) will make XFS retry the
 	operation "N" times before propagating the error.
 
+	Setting the value to "default" will let the default value of the handler,
+	namely the value of default_error/<class>/<error>/max_retries,
+	to decide the error propagation behavior.
+
   retry_timeout_seconds		(Min:  -1  Default:  Varies  Max: 1 day)
 	Define the amount of time (in seconds) that the filesystem is
 	allowed to retry its operations when the specific error is
@@ -462,6 +487,10 @@ to be propagated. The handler configurations are found in the directory:
 	Setting the value to "N" (where 0 < N < Max) will allow XFS to retry the
 	operation for up to "N" seconds before propagating the error.
 
+	Setting the value to "default" will let the default value of the handler,
+	namely the value of default_error/<class>/<error>/retry_timeout_seconds,
+	to decide the error propagation behavior.
+
 Note: The default behaviour for a specific error handler is dependent on both
 the class and error context. For example, the default values for
 "metadata/ENODEV" are "0" rather than "-1" so that this error handler defaults
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-08-31 14:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 3/7] xfs: make the default values of error configuration customizable and workable Hou Tao
2017-08-31 14:15 ` [PATCH 4/7] xfs: merge the initialization table into the default error configuration 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

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.