summaryrefslogtreecommitdiff
path: root/fs/gfs2/util.c
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2018-06-07 11:56:46 +0100
committerBob Peterson <rpeterso@redhat.com>2018-06-21 07:39:44 -0500
commit9e1a9ecd13b9bb421c88135b178577caf4d54f6a (patch)
treebe518fb982b7f8f47c3ed3fa864772d4dd974985 /fs/gfs2/util.c
parentf85c10e24ab9fd8ccb6de3d6061a3110ff3581df (diff)
gfs2: Don't withdraw under a spin lock
In two places, the gfs2_io_error_bh macro is called while holding the sd_ail_lock spin lock. This isn't allowed because gfs2_io_error_bh withdraws the filesystem, which can sleep because it issues a uevent. To fix that, add a gfs2_io_error_bh_wd macro that does withdraw the filesystem and change gfs2_io_error_bh to not withdraw the filesystem. In those places where the new gfs2_io_error_bh is used, withdraw the filesystem after releasing sd_ail_lock. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Bob Peterson <rpeterso@redhat.com> Reviewed-by: Andrew Price <anprice@redhat.com>
Diffstat (limited to 'fs/gfs2/util.c')
-rw-r--r--fs/gfs2/util.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 763d659db91b..59c811de0dc7 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -46,14 +46,16 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...)
test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
return 0;
- va_start(args, fmt);
+ if (fmt) {
+ va_start(args, fmt);
- vaf.fmt = fmt;
- vaf.va = &args;
+ vaf.fmt = fmt;
+ vaf.va = &args;
- fs_err(sdp, "%pV", &vaf);
+ fs_err(sdp, "%pV", &vaf);
- va_end(args);
+ va_end(args);
+ }
if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) {
fs_err(sdp, "about to withdraw this file system\n");
@@ -246,21 +248,21 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
}
/**
- * gfs2_io_error_bh_i - Flag a buffer I/O error and withdraw
- * Returns: -1 if this call withdrew the machine,
- * 0 if it was already withdrawn
+ * gfs2_io_error_bh_i - Flag a buffer I/O error
+ * @withdraw: withdraw the filesystem
*/
-int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
- const char *function, char *file, unsigned int line)
+void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
+ const char *function, char *file, unsigned int line,
+ bool withdraw)
{
- int rv;
- rv = gfs2_lm_withdraw(sdp,
- "fatal: I/O error\n"
- " block = %llu\n"
- " function = %s, file = %s, line = %u\n",
- (unsigned long long)bh->b_blocknr,
- function, file, line);
- return rv;
+ fs_err(sdp,
+ "fatal: I/O error\n"
+ " block = %llu\n"
+ " function = %s, file = %s, line = %u\n",
+ (unsigned long long)bh->b_blocknr,
+ function, file, line);
+ if (withdraw)
+ gfs2_lm_withdraw(sdp, NULL);
}