Accepting request 505781 from home:jeff_mahoney:branches:filesystems
- Fix crash in xfs_repair when threads fail to start (bsc#1019938). * xfs_repair-clear-pthread_t-when-pthread_create-fails.patch * Added xfs_repair-add-prefetch-trace-calls-to-debug-thread-creation-failures.patch * xfs_repair-fix-thread-creation-failure-recovery.patch - fsr: fix uninitialized fs usage after timeout (bsc#1002699). * Added fsr-fix-uninitialized-fs-usage-after-timeout.patch OBS-URL: https://build.opensuse.org/request/show/505781 OBS-URL: https://build.opensuse.org/package/show/filesystems/xfsprogs?expand=0&rev=49
This commit is contained in:
parent
7b8ec2da86
commit
c2598e4729
39
fsr-fix-uninitialized-fs-usage-after-timeout.patch
Normal file
39
fsr-fix-uninitialized-fs-usage-after-timeout.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
Date: Fri, 2 Jun 2017 14:15:41 -0400
|
||||||
|
Subject: fsr: fix uninitialized fs usage after timeout
|
||||||
|
Patch-mainline: Submitted to linux-xfs, 2 Jun 2017
|
||||||
|
References: bsc#1002699
|
||||||
|
|
||||||
|
In the main loop of fsrallfs, we exit when we've hit the timeout but
|
||||||
|
we increment fs before we get there. If we're operating on the last
|
||||||
|
file system in the array, we'll hit an uninitialized fsdesc and
|
||||||
|
crash in fsrall_cleanup.
|
||||||
|
|
||||||
|
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
---
|
||||||
|
fsr/xfs_fsr.c | 4 +---
|
||||||
|
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
|
||||||
|
index 517b75f0..e695c243 100644
|
||||||
|
--- a/fsr/xfs_fsr.c
|
||||||
|
+++ b/fsr/xfs_fsr.c
|
||||||
|
@@ -598,7 +598,7 @@ fsrallfs(char *mtab, int howlong, char *leftofffile)
|
||||||
|
signal(SIGTERM, aborter);
|
||||||
|
|
||||||
|
/* reorg for 'howlong' -- checked in 'fsrfs' */
|
||||||
|
- while (endtime > time(0)) {
|
||||||
|
+ for (; endtime > time(0); fs->npass++, fs++) {
|
||||||
|
pid_t pid;
|
||||||
|
if (fs == fsend)
|
||||||
|
fs = fsbase;
|
||||||
|
@@ -629,8 +629,6 @@ fsrallfs(char *mtab, int howlong, char *leftofffile)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
startino = 0; /* reset after the first time through */
|
||||||
|
- fs->npass++;
|
||||||
|
- fs++;
|
||||||
|
}
|
||||||
|
fsrall_cleanup(endtime <= time(0));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
|||||||
|
From: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
Subject: xfs_repair: add prefetch trace calls to debug thread creation failures
|
||||||
|
Patch-mainline: Submitted, 16 Jan 2017
|
||||||
|
References: bsc#1019938
|
||||||
|
|
||||||
|
When debugging prefetch failures, it's useful to have thread creation
|
||||||
|
failure messages that are output as warnings on stderr in the trace
|
||||||
|
log as well. It's also helpful to see when an AG gets queued behind
|
||||||
|
another one rather than having the thread started directly, which
|
||||||
|
has a separate trace line.
|
||||||
|
|
||||||
|
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
---
|
||||||
|
repair/prefetch.c | 9 ++++++++-
|
||||||
|
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/repair/prefetch.c b/repair/prefetch.c
|
||||||
|
index 044fab2..37d60d6 100644
|
||||||
|
--- a/repair/prefetch.c
|
||||||
|
+++ b/repair/prefetch.c
|
||||||
|
@@ -703,6 +703,8 @@ pf_queuing_worker(
|
||||||
|
if (err != 0) {
|
||||||
|
do_warn(_("failed to create prefetch thread: %s\n"),
|
||||||
|
strerror(err));
|
||||||
|
+ pftrace("failed to create prefetch thread for AG %d: %s",
|
||||||
|
+ args->agno, strerror(err));
|
||||||
|
args->io_threads[i] = 0;
|
||||||
|
if (i == 0) {
|
||||||
|
pf_start_processing(args);
|
||||||
|
@@ -817,6 +819,8 @@ pf_create_prefetch_thread(
|
||||||
|
if (err != 0) {
|
||||||
|
do_warn(_("failed to create prefetch thread: %s\n"),
|
||||||
|
strerror(err));
|
||||||
|
+ pftrace("failed to create prefetch thread for AG %d: %s",
|
||||||
|
+ args->agno, strerror(err));
|
||||||
|
args->queuing_thread = 0;
|
||||||
|
cleanup_inode_prefetch(args);
|
||||||
|
}
|
||||||
|
@@ -882,8 +886,11 @@ start_inode_prefetch(
|
||||||
|
if (prev_args->prefetch_done) {
|
||||||
|
if (!pf_create_prefetch_thread(args))
|
||||||
|
args = NULL;
|
||||||
|
- } else
|
||||||
|
+ } else {
|
||||||
|
prev_args->next_args = args;
|
||||||
|
+ pftrace("queued AG %d after AG %d",
|
||||||
|
+ args->agno, prev_args->agno);
|
||||||
|
+ }
|
||||||
|
pthread_mutex_unlock(&prev_args->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
||||||
|
--
|
||||||
|
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
|
||||||
|
the body of a message to majordomo@vger.kernel.org
|
||||||
|
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
||||||
|
|
||||||
|
|
55
xfs_repair-clear-pthread_t-when-pthread_create-fails.patch
Normal file
55
xfs_repair-clear-pthread_t-when-pthread_create-fails.patch
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
From: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
Subject: xfs_repair: clear pthread_t when pthread_create fails
|
||||||
|
Patch-mainline: Submitted, 16 Jan 2017
|
||||||
|
References: bsc#1019938
|
||||||
|
|
||||||
|
pf_queuing_worker and pf_create_prefetch_thread both try to handle
|
||||||
|
thread creation failure gracefully, but assume that pthread_create
|
||||||
|
doesn't modify the pthread_t when it fails.
|
||||||
|
|
||||||
|
>From the pthread_create man page:
|
||||||
|
On success, pthread_create() returns 0; on error, it returns an error
|
||||||
|
number, and the contents of *thread are undefined.
|
||||||
|
|
||||||
|
In fact, glibc's pthread_create writes the pthread_t value before
|
||||||
|
calling clone(). When we join the created threads in
|
||||||
|
cleanup_inode_prefetch and the cleanup stage of pf_queuing_worker, we
|
||||||
|
assume that if the pthread_t is nonzero that it's a valid thread handle
|
||||||
|
and end up crashing in pthread_join.
|
||||||
|
|
||||||
|
This patch zeros out the handle after pthread_create failure.
|
||||||
|
|
||||||
|
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
---
|
||||||
|
repair/prefetch.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/repair/prefetch.c b/repair/prefetch.c
|
||||||
|
index ff50606..044fab2 100644
|
||||||
|
--- a/repair/prefetch.c
|
||||||
|
+++ b/repair/prefetch.c
|
||||||
|
@@ -703,6 +703,7 @@ pf_queuing_worker(
|
||||||
|
if (err != 0) {
|
||||||
|
do_warn(_("failed to create prefetch thread: %s\n"),
|
||||||
|
strerror(err));
|
||||||
|
+ args->io_threads[i] = 0;
|
||||||
|
if (i == 0) {
|
||||||
|
pf_start_processing(args);
|
||||||
|
return NULL;
|
||||||
|
@@ -816,6 +817,7 @@ pf_create_prefetch_thread(
|
||||||
|
if (err != 0) {
|
||||||
|
do_warn(_("failed to create prefetch thread: %s\n"),
|
||||||
|
strerror(err));
|
||||||
|
+ args->queuing_thread = 0;
|
||||||
|
cleanup_inode_prefetch(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
||||||
|
--
|
||||||
|
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
|
||||||
|
the body of a message to majordomo@vger.kernel.org
|
||||||
|
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
||||||
|
|
||||||
|
|
136
xfs_repair-fix-thread-creation-failure-recovery.patch
Normal file
136
xfs_repair-fix-thread-creation-failure-recovery.patch
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
From: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
Subject: xfs_repair: fix thread creation failure recovery
|
||||||
|
Patch-mainline: Submitted, 16 Jan 2017
|
||||||
|
References: bsc#1019938
|
||||||
|
|
||||||
|
When pf_create_prefetch_thread fails, it tears down the args struct
|
||||||
|
and frees it. This causes a use-after-free in prefetch_ag_range, which
|
||||||
|
then passes the now-invalid pointer to start_inode_prefetch. The struct
|
||||||
|
is only freed when the queuing thread can't be started. When we can't
|
||||||
|
start even one worker thread, we mark the args ready for processing and
|
||||||
|
allow it to proceed single-threaded. Unfortunately, this only marks
|
||||||
|
the current args ready for processing and since we return immediately,
|
||||||
|
the call to pf_create_prefetch_thread at the end of pf_queuing_worker
|
||||||
|
never gets called and we wait forever for prefetch to start on the
|
||||||
|
next AG.
|
||||||
|
|
||||||
|
This patch factors out the cleanup into a new pf_skip_prefetch_thread
|
||||||
|
that is called when we fail to create either the queuing thread or
|
||||||
|
the first of the workers. It marks the args ready for processing, marks
|
||||||
|
it done so start_inode_prefetch doesn't add another AG to the list, and
|
||||||
|
tries to start a new thread for the next AG in the list. We also clear
|
||||||
|
->next_args and check for it in cleanup_inode_prefetch so this condition
|
||||||
|
is easier to catch should it arise again.
|
||||||
|
|
||||||
|
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||||
|
---
|
||||||
|
repair/prefetch.c | 38 ++++++++++++++++++++++++++++++++------
|
||||||
|
1 file changed, 32 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/repair/prefetch.c b/repair/prefetch.c
|
||||||
|
index 37d60d6..4c74b6e 100644
|
||||||
|
--- a/repair/prefetch.c
|
||||||
|
+++ b/repair/prefetch.c
|
||||||
|
@@ -679,11 +679,32 @@ static int
|
||||||
|
pf_create_prefetch_thread(
|
||||||
|
prefetch_args_t *args);
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * If we fail to create the queuing thread or can't create even one
|
||||||
|
+ * prefetch thread, we need to let processing continue without it.
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+pf_skip_prefetch_thread(prefetch_args_t *args)
|
||||||
|
+{
|
||||||
|
+ prefetch_args_t *next;
|
||||||
|
+
|
||||||
|
+ pthread_mutex_lock(&args->lock);
|
||||||
|
+ args->prefetch_done = 1;
|
||||||
|
+ pf_start_processing(args);
|
||||||
|
+ next = args->next_args;
|
||||||
|
+ args->next_args = NULL;
|
||||||
|
+ pthread_mutex_unlock(&args->lock);
|
||||||
|
+
|
||||||
|
+ if (next)
|
||||||
|
+ pf_create_prefetch_thread(next);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void *
|
||||||
|
pf_queuing_worker(
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
prefetch_args_t *args = param;
|
||||||
|
+ prefetch_args_t *next_args;
|
||||||
|
int num_inos;
|
||||||
|
ino_tree_node_t *irec;
|
||||||
|
ino_tree_node_t *cur_irec;
|
||||||
|
@@ -707,7 +728,7 @@ pf_queuing_worker(
|
||||||
|
args->agno, strerror(err));
|
||||||
|
args->io_threads[i] = 0;
|
||||||
|
if (i == 0) {
|
||||||
|
- pf_start_processing(args);
|
||||||
|
+ pf_skip_prefetch_thread(args);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
@@ -798,11 +819,13 @@ pf_queuing_worker(
|
||||||
|
ASSERT(btree_is_empty(args->io_queue));
|
||||||
|
|
||||||
|
args->prefetch_done = 1;
|
||||||
|
- if (args->next_args)
|
||||||
|
- pf_create_prefetch_thread(args->next_args);
|
||||||
|
-
|
||||||
|
+ next_args = args->next_args;
|
||||||
|
+ args->next_args = NULL;
|
||||||
|
pthread_mutex_unlock(&args->lock);
|
||||||
|
|
||||||
|
+ if (next_args)
|
||||||
|
+ pf_create_prefetch_thread(next_args);
|
||||||
|
+
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -822,7 +845,7 @@ pf_create_prefetch_thread(
|
||||||
|
pftrace("failed to create prefetch thread for AG %d: %s",
|
||||||
|
args->agno, strerror(err));
|
||||||
|
args->queuing_thread = 0;
|
||||||
|
- cleanup_inode_prefetch(args);
|
||||||
|
+ pf_skip_prefetch_thread(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err == 0;
|
||||||
|
@@ -884,14 +907,15 @@ start_inode_prefetch(
|
||||||
|
} else {
|
||||||
|
pthread_mutex_lock(&prev_args->lock);
|
||||||
|
if (prev_args->prefetch_done) {
|
||||||
|
+ pthread_mutex_unlock(&prev_args->lock);
|
||||||
|
if (!pf_create_prefetch_thread(args))
|
||||||
|
args = NULL;
|
||||||
|
} else {
|
||||||
|
prev_args->next_args = args;
|
||||||
|
pftrace("queued AG %d after AG %d",
|
||||||
|
args->agno, prev_args->agno);
|
||||||
|
+ pthread_mutex_unlock(&prev_args->lock);
|
||||||
|
}
|
||||||
|
- pthread_mutex_unlock(&prev_args->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
@@ -1066,6 +1090,8 @@ cleanup_inode_prefetch(
|
||||||
|
|
||||||
|
pftrace("AG %d prefetch done", args->agno);
|
||||||
|
|
||||||
|
+ ASSERT(args->next_args == NULL);
|
||||||
|
+
|
||||||
|
pthread_mutex_destroy(&args->lock);
|
||||||
|
pthread_cond_destroy(&args->start_reading);
|
||||||
|
pthread_cond_destroy(&args->start_processing);
|
||||||
|
--
|
||||||
|
2.7.1
|
||||||
|
|
||||||
|
--
|
||||||
|
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
|
||||||
|
the body of a message to majordomo@vger.kernel.org
|
||||||
|
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
||||||
|
|
||||||
|
|
@ -1,3 +1,17 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Jun 22 20:15:28 UTC 2017 - jeffm@suse.com
|
||||||
|
|
||||||
|
- Fix crash in xfs_repair when threads fail to start (bsc#1019938).
|
||||||
|
* xfs_repair-clear-pthread_t-when-pthread_create-fails.patch
|
||||||
|
* Added xfs_repair-add-prefetch-trace-calls-to-debug-thread-creation-failures.patch
|
||||||
|
* xfs_repair-fix-thread-creation-failure-recovery.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Jun 2 18:23:03 UTC 2017 - jeffm@suse.com
|
||||||
|
|
||||||
|
- fsr: fix uninitialized fs usage after timeout (bsc#1002699).
|
||||||
|
* Added fsr-fix-uninitialized-fs-usage-after-timeout.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue May 16 14:52:53 UTC 2017 - jeffm@suse.com
|
Tue May 16 14:52:53 UTC 2017 - jeffm@suse.com
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@ Source2: %{name}.keyring
|
|||||||
Source3: module-setup.sh.in
|
Source3: module-setup.sh.in
|
||||||
Source4: dracut-fsck-help.txt
|
Source4: dracut-fsck-help.txt
|
||||||
Patch0: xfsprogs-docdir.diff
|
Patch0: xfsprogs-docdir.diff
|
||||||
|
Patch1: fsr-fix-uninitialized-fs-usage-after-timeout.patch
|
||||||
|
Patch2: xfs_repair-clear-pthread_t-when-pthread_create-fails.patch
|
||||||
|
Patch3: xfs_repair-add-prefetch-trace-calls-to-debug-thread-creation-failures.patch
|
||||||
|
Patch4: xfs_repair-fix-thread-creation-failure-recovery.patch
|
||||||
BuildRequires: libblkid-devel
|
BuildRequires: libblkid-devel
|
||||||
BuildRequires: readline-devel
|
BuildRequires: readline-devel
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||||
@ -42,6 +46,7 @@ Supplements: filesystem(xfs)
|
|||||||
%if 0%{?suse_version} >= 1310
|
%if 0%{?suse_version} >= 1310
|
||||||
BuildRequires: suse-module-tools
|
BuildRequires: suse-module-tools
|
||||||
%endif
|
%endif
|
||||||
|
BuildRequires: xz
|
||||||
|
|
||||||
%description
|
%description
|
||||||
A set of commands to use the XFS file system, including mkfs.xfs.
|
A set of commands to use the XFS file system, including mkfs.xfs.
|
||||||
@ -75,6 +80,10 @@ want to install xfsprogs.
|
|||||||
%if 0%{?suse_version}
|
%if 0%{?suse_version}
|
||||||
%patch0
|
%patch0
|
||||||
%endif
|
%endif
|
||||||
|
%patch1 -p1
|
||||||
|
%patch2 -p1
|
||||||
|
%patch3 -p1
|
||||||
|
%patch4 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
export OPTIMIZER="-fPIC"
|
export OPTIMIZER="-fPIC"
|
||||||
|
Loading…
Reference in New Issue
Block a user