mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
Bug fixes for 6.9-rc2:
* 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. Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQjMC4mbgVeU7MxEIYH7y4RirJu9AUCZgKa+AAKCRAH7y4RirJu 9IL1APwPBMzSowijBI/rCD5BGlISn7mCRlZwvyXE1avmRmbQPAEApU5yRhBHWi62 629azfSr1I5m678xM7WQKh6X3/VUDAg= =pqNH -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
712e14250d
@ -530,7 +530,8 @@ xfs_validate_sb_common(
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -1323,8 +1324,10 @@ xfs_sb_get_secondary(
|
||||
}
|
||||
|
||||
/*
|
||||
* sunit, swidth, sectorsize(optional with 0) should be all in bytes,
|
||||
* so users won't be confused by values in error messages.
|
||||
* sunit, swidth, sectorsize(optional with 0) should be all in bytes, so users
|
||||
* 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
|
||||
xfs_validate_stripe_geometry(
|
||||
@ -1332,20 +1335,21 @@ xfs_validate_stripe_geometry(
|
||||
__s64 sunit,
|
||||
__s64 swidth,
|
||||
int sectorsize,
|
||||
bool may_repair,
|
||||
bool silent)
|
||||
{
|
||||
if (swidth > INT_MAX) {
|
||||
if (!silent)
|
||||
xfs_notice(mp,
|
||||
"stripe width (%lld) is too large", swidth);
|
||||
return false;
|
||||
goto check_override;
|
||||
}
|
||||
|
||||
if (sunit > swidth) {
|
||||
if (!silent)
|
||||
xfs_notice(mp,
|
||||
"stripe unit (%lld) is larger than the stripe width (%lld)", sunit, swidth);
|
||||
return false;
|
||||
goto check_override;
|
||||
}
|
||||
|
||||
if (sectorsize && (int)sunit % sectorsize) {
|
||||
@ -1353,21 +1357,21 @@ xfs_validate_stripe_geometry(
|
||||
xfs_notice(mp,
|
||||
"stripe unit (%lld) must be a multiple of the sector size (%d)",
|
||||
sunit, sectorsize);
|
||||
return false;
|
||||
goto check_override;
|
||||
}
|
||||
|
||||
if (sunit && !swidth) {
|
||||
if (!silent)
|
||||
xfs_notice(mp,
|
||||
"invalid stripe unit (%lld) and stripe width of 0", sunit);
|
||||
return false;
|
||||
goto check_override;
|
||||
}
|
||||
|
||||
if (!sunit && swidth) {
|
||||
if (!silent)
|
||||
xfs_notice(mp,
|
||||
"invalid stripe width (%lld) and stripe unit of 0", swidth);
|
||||
return false;
|
||||
goto check_override;
|
||||
}
|
||||
|
||||
if (sunit && (int)swidth % (int)sunit) {
|
||||
@ -1375,9 +1379,27 @@ xfs_validate_stripe_geometry(
|
||||
xfs_notice(mp,
|
||||
"stripe width (%lld) must be a multiple of the stripe unit (%lld)",
|
||||
swidth, sunit);
|
||||
return false;
|
||||
goto check_override;
|
||||
}
|
||||
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,
|
||||
struct xfs_trans *tp, xfs_agnumber_t agno,
|
||||
struct xfs_buf **bpp);
|
||||
|
||||
extern bool xfs_validate_stripe_geometry(struct xfs_mount *mp,
|
||||
__s64 sunit, __s64 swidth, int sectorsize, bool silent);
|
||||
bool xfs_validate_stripe_geometry(struct xfs_mount *mp,
|
||||
__s64 sunit, __s64 swidth, int sectorsize, bool may_repair,
|
||||
bool silent);
|
||||
|
||||
uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents);
|
||||
|
||||
|
@ -1044,9 +1044,7 @@ xchk_irele(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
if (current->journal_info != NULL) {
|
||||
ASSERT(current->journal_info == sc->tp);
|
||||
|
||||
if (sc->tp) {
|
||||
/*
|
||||
* If we are in a transaction, we /cannot/ drop the inode
|
||||
* ourselves, because the VFS will trigger writeback, which
|
||||
|
@ -503,13 +503,6 @@ xfs_vm_writepages(
|
||||
{
|
||||
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);
|
||||
return iomap_writepages(mapping, wbc, &wpc.ctx, &xfs_writeback_ops);
|
||||
}
|
||||
|
@ -2039,8 +2039,10 @@ xfs_inodegc_want_queue_work(
|
||||
* - Memory shrinkers queued the inactivation worker and it hasn't finished.
|
||||
* - The queue depth exceeds the maximum allowable percpu backlog.
|
||||
*
|
||||
* Note: If the current thread is running a transaction, we don't ever want to
|
||||
* wait for other transactions because that could introduce a deadlock.
|
||||
* Note: If we are in a NOFS context here (e.g. current thread is running a
|
||||
* 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
|
||||
xfs_inodegc_want_flush_work(
|
||||
@ -2048,7 +2050,7 @@ xfs_inodegc_want_flush_work(
|
||||
unsigned int items,
|
||||
unsigned int shrinker_hits)
|
||||
{
|
||||
if (current->journal_info)
|
||||
if (current->flags & PF_MEMALLOC_NOFS)
|
||||
return false;
|
||||
|
||||
if (shrinker_hits > 0)
|
||||
|
@ -268,19 +268,14 @@ static inline void
|
||||
xfs_trans_set_context(
|
||||
struct xfs_trans *tp)
|
||||
{
|
||||
ASSERT(current->journal_info == NULL);
|
||||
tp->t_pflags = memalloc_nofs_save();
|
||||
current->journal_info = tp;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_trans_clear_context(
|
||||
struct xfs_trans *tp)
|
||||
{
|
||||
if (current->journal_info == tp) {
|
||||
memalloc_nofs_restore(tp->t_pflags);
|
||||
current->journal_info = NULL;
|
||||
}
|
||||
memalloc_nofs_restore(tp->t_pflags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -288,10 +283,8 @@ xfs_trans_switch_context(
|
||||
struct xfs_trans *old_tp,
|
||||
struct xfs_trans *new_tp)
|
||||
{
|
||||
ASSERT(current->journal_info == old_tp);
|
||||
new_tp->t_pflags = old_tp->t_pflags;
|
||||
old_tp->t_pflags = 0;
|
||||
current->journal_info = new_tp;
|
||||
}
|
||||
|
||||
#endif /* __XFS_TRANS_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user