]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
xfs: add "fail at unmount" error handling configuration
authorCarlos Maiolino <cmaiolino@redhat.com>
Wed, 18 May 2016 01:11:27 +0000 (11:11 +1000)
committerChuck Anderson <chuck.anderson@oracle.com>
Sat, 10 Jun 2017 00:25:17 +0000 (17:25 -0700)
If we take "retry forever" literally on metadata IO errors, we can
hang at unmount, once it retries those writes forever. This is the
default behavior, unfortunately.

Add an error configuration option for this behavior and default it
to "fail" so that an unmount will trigger actuall errors, a shutdown
and allow the unmount to succeed. It will be noisy, though, as it
will log the errors and shutdown that occurs.

To fix this, we need to mark the filesystem as being in the process
of unmounting. Do this with a mount flag that is added at the
appropriate time (i.e. before the blocking AIL sync). We also need
to add this flag if mount fails after the initial phase of log
recovery has been run.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
(cherry picked from commit e6b3bb78962e65c4ad125598755cfbf2a8779e86)

Orabug: 26130728

Signed-off-by: Kirtikar Kashyap <kirtikar.kashyap@oracle.com>
Reviewed-by: Jack Vogel <jack.vogel@oracle.com>
 Conflicts:
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h

fs/xfs/xfs_buf_item.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_sysfs.c

index 713a3c7a776d02688bc150c7181a5fc9c87e3ded..be81eb1b4a3918cc59cb000dd10712ca4ecb4689 100644 (file)
@@ -1112,6 +1112,10 @@ xfs_buf_iodone_callback_error(
            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)
+               goto permanent_error;
+
        /* still a transient error, higher layers will retry */
        xfs_buf_ioerror(bp, 0);
        xfs_buf_relse(bp);
index 902718596c96e86bb1ca790ee4deda83bf0b2a38..1eedb66e88bcc9962fa4e5e32dd495264fc16130 100644 (file)
@@ -691,6 +691,9 @@ xfs_mountfs(
 
        xfs_set_maxicount(mp);
 
+       /* enable fail_at_unmount as default */
+       mp->m_fail_unmount = 1;
+
        error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype, NULL, mp->m_fsname);
        if (error)
                goto out;
@@ -952,6 +955,7 @@ xfs_mountfs(
  out_rele_rip:
        IRELE(rip);
  out_log_dealloc:
+       mp->m_flags |= XFS_MOUNT_UNMOUNTING;
        xfs_log_unmount(mp);
  out_fail_wait:
        if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
@@ -1002,6 +1006,14 @@ xfs_unmountfs(
         */
        xfs_log_force(mp, XFS_LOG_SYNC);
 
+       /*
+        * We now need to tell the world we are unmounting. This will allow
+        * us to detect that the filesystem is going away and we should error
+        * out anything that we have been retrying in the background. This will
+        * prevent neverending retries in AIL pushing from hanging the unmount.
+        */
+       mp->m_flags |= XFS_MOUNT_UNMOUNTING;
+
        /*
         * Flush all pending changes from the AIL.
         */
index ad4ba7898848b1dc96c0b43a4208946fc7ae7921..d4d0955f2940cc8190e54adb6c950360a709327d 100644 (file)
@@ -174,6 +174,8 @@ typedef struct xfs_mount {
         * to various other kinds of pain inflicted on the pNFS server.
         */
        __uint32_t              m_generation;
+
+       bool                    m_fail_unmount;
 } xfs_mount_t;
 
 /*
@@ -182,6 +184,7 @@ typedef struct xfs_mount {
 #define XFS_MOUNT_WSYNC                (1ULL << 0)     /* for nfs - all metadata ops
                                                   must be synchronous except
                                                   for space allocations */
+#define XFS_MOUNT_UNMOUNTING   (1ULL << 1)     /* filesystem is unmounting */
 #define XFS_MOUNT_WAS_CLEAN    (1ULL << 3)
 #define XFS_MOUNT_FS_SHUTDOWN  (1ULL << 4)     /* atomic stop of all filesystem
                                                   operations, typically for
index fb2f3069291d2d14907225bb0ba151d20f313328..2be00e7822c74ef8e0e77288255a7fcdf515c7c2 100644 (file)
@@ -290,6 +290,13 @@ to_error_cfg(struct kobject *kobject)
        return container_of(kobj, struct xfs_error_cfg, kobj);
 }
 
+static inline struct xfs_mount *
+err_to_mp(struct kobject *kobject)
+{
+       struct xfs_kobj *kobj = to_kobj(kobject);
+       return container_of(kobj, struct xfs_mount, m_error_kobj);
+}
+
 static ssize_t
 max_retries_show(
        struct kobject  *kobject,
@@ -356,6 +363,38 @@ retry_timeout_seconds_store(
 }
 XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
 
+static ssize_t
+fail_at_unmount_show(
+       struct kobject  *kobject,
+       char            *buf)
+{
+       struct xfs_mount        *mp = err_to_mp(kobject);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount);
+}
+
+static ssize_t
+fail_at_unmount_store(
+       struct kobject  *kobject,
+       const char      *buf,
+       size_t          count)
+{
+       struct xfs_mount        *mp = err_to_mp(kobject);
+       int             ret;
+       int             val;
+
+       ret = kstrtoint(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val < 0 || val > 1)
+               return -EINVAL;
+
+       mp->m_fail_unmount = val;
+       return count;
+}
+XFS_SYSFS_ATTR_RW(fail_at_unmount);
+
 static struct attribute *xfs_error_attrs[] = {
        ATTR_LIST(max_retries),
        ATTR_LIST(retry_timeout_seconds),
@@ -371,6 +410,7 @@ struct kobj_type xfs_error_cfg_ktype = {
 
 struct kobj_type xfs_error_ktype = {
        .release = xfs_sysfs_release,
+       .sysfs_ops = &xfs_sysfs_ops,
 };
 
 /*
@@ -457,6 +497,12 @@ xfs_error_sysfs_init(
        if (error)
                return error;
 
+       error = sysfs_create_file(&mp->m_error_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,