diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2018-06-07 12:56:46 +0200 |
---|---|---|
committer | Bob Peterson <rpeterso@redhat.com> | 2018-06-21 14:39:44 +0200 |
commit | 9e1a9ecd13b9bb421c88135b178577caf4d54f6a (patch) | |
tree | be518fb982b7f8f47c3ed3fa864772d4dd974985 /fs/gfs2/util.c | |
parent | gfs2: eliminate rs_inum and reduce the size of gfs2 inodes (diff) | |
download | linux-9e1a9ecd13b9bb421c88135b178577caf4d54f6a.tar.xz linux-9e1a9ecd13b9bb421c88135b178577caf4d54f6a.zip |
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.c | 38 |
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); } |