Commit 712e1425 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-6.9-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Chandan Babu:

 - Allow stripe unit/width value passed via mount option to be written
   over existing values in the super block

 - Do not set current->journal_info to avoid its value from being miused
   by another filesystem context

* tag 'xfs-6.9-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: don't use current->journal_info
  xfs: allow sunit mount option to repair bad primary sb stripe values
parents fe764a75 f2e812c1
...@@ -530,7 +530,8 @@ xfs_validate_sb_common( ...@@ -530,7 +530,8 @@ xfs_validate_sb_common(
} }
if (!xfs_validate_stripe_geometry(mp, XFS_FSB_TO_B(mp, sbp->sb_unit), if (!xfs_validate_stripe_geometry(mp, XFS_FSB_TO_B(mp, sbp->sb_unit),
XFS_FSB_TO_B(mp, sbp->sb_width), 0, false)) XFS_FSB_TO_B(mp, sbp->sb_width), 0,
xfs_buf_daddr(bp) == XFS_SB_DADDR, false))
return -EFSCORRUPTED; return -EFSCORRUPTED;
/* /*
...@@ -1323,8 +1324,10 @@ xfs_sb_get_secondary( ...@@ -1323,8 +1324,10 @@ xfs_sb_get_secondary(
} }
/* /*
* sunit, swidth, sectorsize(optional with 0) should be all in bytes, * sunit, swidth, sectorsize(optional with 0) should be all in bytes, so users
* so users won't be confused by values in error messages. * won't be confused by values in error messages. This function returns false
* if the stripe geometry is invalid and the caller is unable to repair the
* stripe configuration later in the mount process.
*/ */
bool bool
xfs_validate_stripe_geometry( xfs_validate_stripe_geometry(
...@@ -1332,20 +1335,21 @@ xfs_validate_stripe_geometry( ...@@ -1332,20 +1335,21 @@ xfs_validate_stripe_geometry(
__s64 sunit, __s64 sunit,
__s64 swidth, __s64 swidth,
int sectorsize, int sectorsize,
bool may_repair,
bool silent) bool silent)
{ {
if (swidth > INT_MAX) { if (swidth > INT_MAX) {
if (!silent) if (!silent)
xfs_notice(mp, xfs_notice(mp,
"stripe width (%lld) is too large", swidth); "stripe width (%lld) is too large", swidth);
return false; goto check_override;
} }
if (sunit > swidth) { if (sunit > swidth) {
if (!silent) if (!silent)
xfs_notice(mp, xfs_notice(mp,
"stripe unit (%lld) is larger than the stripe width (%lld)", sunit, swidth); "stripe unit (%lld) is larger than the stripe width (%lld)", sunit, swidth);
return false; goto check_override;
} }
if (sectorsize && (int)sunit % sectorsize) { if (sectorsize && (int)sunit % sectorsize) {
...@@ -1353,21 +1357,21 @@ xfs_validate_stripe_geometry( ...@@ -1353,21 +1357,21 @@ xfs_validate_stripe_geometry(
xfs_notice(mp, xfs_notice(mp,
"stripe unit (%lld) must be a multiple of the sector size (%d)", "stripe unit (%lld) must be a multiple of the sector size (%d)",
sunit, sectorsize); sunit, sectorsize);
return false; goto check_override;
} }
if (sunit && !swidth) { if (sunit && !swidth) {
if (!silent) if (!silent)
xfs_notice(mp, xfs_notice(mp,
"invalid stripe unit (%lld) and stripe width of 0", sunit); "invalid stripe unit (%lld) and stripe width of 0", sunit);
return false; goto check_override;
} }
if (!sunit && swidth) { if (!sunit && swidth) {
if (!silent) if (!silent)
xfs_notice(mp, xfs_notice(mp,
"invalid stripe width (%lld) and stripe unit of 0", swidth); "invalid stripe width (%lld) and stripe unit of 0", swidth);
return false; goto check_override;
} }
if (sunit && (int)swidth % (int)sunit) { if (sunit && (int)swidth % (int)sunit) {
...@@ -1375,9 +1379,27 @@ xfs_validate_stripe_geometry( ...@@ -1375,9 +1379,27 @@ xfs_validate_stripe_geometry(
xfs_notice(mp, xfs_notice(mp,
"stripe width (%lld) must be a multiple of the stripe unit (%lld)", "stripe width (%lld) must be a multiple of the stripe unit (%lld)",
swidth, sunit); swidth, sunit);
return false; goto check_override;
} }
return true; return true;
check_override:
if (!may_repair)
return false;
/*
* During mount, mp->m_dalign will not be set unless the sunit mount
* option was set. If it was set, ignore the bad stripe alignment values
* and allow the validation and overwrite later in the mount process to
* attempt to overwrite the bad stripe alignment values with the values
* supplied by mount options.
*/
if (!mp->m_dalign)
return false;
if (!silent)
xfs_notice(mp,
"Will try to correct with specified mount options sunit (%d) and swidth (%d)",
BBTOB(mp->m_dalign), BBTOB(mp->m_swidth));
return true;
} }
/* /*
......
...@@ -35,8 +35,9 @@ extern int xfs_sb_get_secondary(struct xfs_mount *mp, ...@@ -35,8 +35,9 @@ extern int xfs_sb_get_secondary(struct xfs_mount *mp,
struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_trans *tp, xfs_agnumber_t agno,
struct xfs_buf **bpp); struct xfs_buf **bpp);
extern bool xfs_validate_stripe_geometry(struct xfs_mount *mp, bool xfs_validate_stripe_geometry(struct xfs_mount *mp,
__s64 sunit, __s64 swidth, int sectorsize, bool silent); __s64 sunit, __s64 swidth, int sectorsize, bool may_repair,
bool silent);
uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents); uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents);
......
...@@ -1044,9 +1044,7 @@ xchk_irele( ...@@ -1044,9 +1044,7 @@ xchk_irele(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_inode *ip) struct xfs_inode *ip)
{ {
if (current->journal_info != NULL) { if (sc->tp) {
ASSERT(current->journal_info == sc->tp);
/* /*
* If we are in a transaction, we /cannot/ drop the inode * If we are in a transaction, we /cannot/ drop the inode
* ourselves, because the VFS will trigger writeback, which * ourselves, because the VFS will trigger writeback, which
......
...@@ -503,13 +503,6 @@ xfs_vm_writepages( ...@@ -503,13 +503,6 @@ xfs_vm_writepages(
{ {
struct xfs_writepage_ctx wpc = { }; struct xfs_writepage_ctx wpc = { };
/*
* Writing back data in a transaction context can result in recursive
* transactions. This is bad, so issue a warning and get out of here.
*/
if (WARN_ON_ONCE(current->journal_info))
return 0;
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED); xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
return iomap_writepages(mapping, wbc, &wpc.ctx, &xfs_writeback_ops); return iomap_writepages(mapping, wbc, &wpc.ctx, &xfs_writeback_ops);
} }
......
...@@ -2039,8 +2039,10 @@ xfs_inodegc_want_queue_work( ...@@ -2039,8 +2039,10 @@ xfs_inodegc_want_queue_work(
* - Memory shrinkers queued the inactivation worker and it hasn't finished. * - Memory shrinkers queued the inactivation worker and it hasn't finished.
* - The queue depth exceeds the maximum allowable percpu backlog. * - The queue depth exceeds the maximum allowable percpu backlog.
* *
* Note: If the current thread is running a transaction, we don't ever want to * Note: If we are in a NOFS context here (e.g. current thread is running a
* wait for other transactions because that could introduce a deadlock. * transaction) the we don't want to block here as inodegc progress may require
* filesystem resources we hold to make progress and that could result in a
* deadlock. Hence we skip out of here if we are in a scoped NOFS context.
*/ */
static inline bool static inline bool
xfs_inodegc_want_flush_work( xfs_inodegc_want_flush_work(
...@@ -2048,7 +2050,7 @@ xfs_inodegc_want_flush_work( ...@@ -2048,7 +2050,7 @@ xfs_inodegc_want_flush_work(
unsigned int items, unsigned int items,
unsigned int shrinker_hits) unsigned int shrinker_hits)
{ {
if (current->journal_info) if (current->flags & PF_MEMALLOC_NOFS)
return false; return false;
if (shrinker_hits > 0) if (shrinker_hits > 0)
......
...@@ -268,19 +268,14 @@ static inline void ...@@ -268,19 +268,14 @@ static inline void
xfs_trans_set_context( xfs_trans_set_context(
struct xfs_trans *tp) struct xfs_trans *tp)
{ {
ASSERT(current->journal_info == NULL);
tp->t_pflags = memalloc_nofs_save(); tp->t_pflags = memalloc_nofs_save();
current->journal_info = tp;
} }
static inline void static inline void
xfs_trans_clear_context( xfs_trans_clear_context(
struct xfs_trans *tp) struct xfs_trans *tp)
{ {
if (current->journal_info == tp) { memalloc_nofs_restore(tp->t_pflags);
memalloc_nofs_restore(tp->t_pflags);
current->journal_info = NULL;
}
} }
static inline void static inline void
...@@ -288,10 +283,8 @@ xfs_trans_switch_context( ...@@ -288,10 +283,8 @@ xfs_trans_switch_context(
struct xfs_trans *old_tp, struct xfs_trans *old_tp,
struct xfs_trans *new_tp) struct xfs_trans *new_tp)
{ {
ASSERT(current->journal_info == old_tp);
new_tp->t_pflags = old_tp->t_pflags; new_tp->t_pflags = old_tp->t_pflags;
old_tp->t_pflags = 0; old_tp->t_pflags = 0;
current->journal_info = new_tp;
} }
#endif /* __XFS_TRANS_H__ */ #endif /* __XFS_TRANS_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment