Merge tag 'xfs-fixes-6.15-rc7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Carlos Maiolino: "This includes a bug fix for a possible data corruption vector on the zoned allocator garbage collector" * tag 'xfs-fixes-6.15-rc7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: Fix comment on xfs_trans_ail_update_bulk() xfs: Fix a comment on xfs_ail_delete xfs: Fail remount with noattr2 on a v5 with v4 enabled xfs: fix zoned GC data corruption due to wrong bv_offset xfs: free up mp->m_free[0].count in error case
This commit is contained in:
+27
-1
@@ -1149,7 +1149,7 @@ xfs_init_percpu_counters(
|
||||
return 0;
|
||||
|
||||
free_freecounters:
|
||||
while (--i > 0)
|
||||
while (--i >= 0)
|
||||
percpu_counter_destroy(&mp->m_free[i].count);
|
||||
percpu_counter_destroy(&mp->m_delalloc_rtextents);
|
||||
free_delalloc:
|
||||
@@ -2114,6 +2114,21 @@ xfs_fs_reconfigure(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* attr2 -> noattr2 */
|
||||
if (xfs_has_noattr2(new_mp)) {
|
||||
if (xfs_has_crc(mp)) {
|
||||
xfs_warn(mp,
|
||||
"attr2 is always enabled for a V5 filesystem - can't be changed.");
|
||||
return -EINVAL;
|
||||
}
|
||||
mp->m_features &= ~XFS_FEAT_ATTR2;
|
||||
mp->m_features |= XFS_FEAT_NOATTR2;
|
||||
} else if (xfs_has_attr2(new_mp)) {
|
||||
/* noattr2 -> attr2 */
|
||||
mp->m_features &= ~XFS_FEAT_NOATTR2;
|
||||
mp->m_features |= XFS_FEAT_ATTR2;
|
||||
}
|
||||
|
||||
/* inode32 -> inode64 */
|
||||
if (xfs_has_small_inums(mp) && !xfs_has_small_inums(new_mp)) {
|
||||
mp->m_features &= ~XFS_FEAT_SMALL_INUMS;
|
||||
@@ -2126,6 +2141,17 @@ xfs_fs_reconfigure(
|
||||
mp->m_maxagi = xfs_set_inode_alloc(mp, mp->m_sb.sb_agcount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that mp has been modified according to the remount options, we
|
||||
* do a final option validation with xfs_finish_flags() just like it is
|
||||
* just like it is done during mount. We cannot use
|
||||
* done during mount. We cannot use xfs_finish_flags() on new_mp as it
|
||||
* contains only the user given options.
|
||||
*/
|
||||
error = xfs_finish_flags(mp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* ro -> rw */
|
||||
if (xfs_is_readonly(mp) && !(flags & SB_RDONLY)) {
|
||||
error = xfs_remount_rw(mp);
|
||||
|
||||
+18
-16
@@ -315,7 +315,7 @@ xfs_ail_splice(
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the given item from the AIL. Return a pointer to the item.
|
||||
* Delete the given item from the AIL.
|
||||
*/
|
||||
static void
|
||||
xfs_ail_delete(
|
||||
@@ -777,26 +777,28 @@ xfs_ail_update_finish(
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_trans_ail_update - bulk AIL insertion operation.
|
||||
* xfs_trans_ail_update_bulk - bulk AIL insertion operation.
|
||||
*
|
||||
* @xfs_trans_ail_update takes an array of log items that all need to be
|
||||
* @xfs_trans_ail_update_bulk takes an array of log items that all need to be
|
||||
* positioned at the same LSN in the AIL. If an item is not in the AIL, it will
|
||||
* be added. Otherwise, it will be repositioned by removing it and re-adding
|
||||
* it to the AIL. If we move the first item in the AIL, update the log tail to
|
||||
* match the new minimum LSN in the AIL.
|
||||
* be added. Otherwise, it will be repositioned by removing it and re-adding
|
||||
* it to the AIL.
|
||||
*
|
||||
* This function takes the AIL lock once to execute the update operations on
|
||||
* all the items in the array, and as such should not be called with the AIL
|
||||
* lock held. As a result, once we have the AIL lock, we need to check each log
|
||||
* item LSN to confirm it needs to be moved forward in the AIL.
|
||||
* If we move the first item in the AIL, update the log tail to match the new
|
||||
* minimum LSN in the AIL.
|
||||
*
|
||||
* To optimise the insert operation, we delete all the items from the AIL in
|
||||
* the first pass, moving them into a temporary list, then splice the temporary
|
||||
* list into the correct position in the AIL. This avoids needing to do an
|
||||
* insert operation on every item.
|
||||
* This function should be called with the AIL lock held.
|
||||
*
|
||||
* This function must be called with the AIL lock held. The lock is dropped
|
||||
* before returning.
|
||||
* To optimise the insert operation, we add all items to a temporary list, then
|
||||
* splice this list into the correct position in the AIL.
|
||||
*
|
||||
* Items that are already in the AIL are first deleted from their current
|
||||
* location before being added to the temporary list.
|
||||
*
|
||||
* This avoids needing to do an insert operation on every item.
|
||||
*
|
||||
* The AIL lock is dropped by xfs_ail_update_finish() before returning to
|
||||
* the caller.
|
||||
*/
|
||||
void
|
||||
xfs_trans_ail_update_bulk(
|
||||
|
||||
@@ -807,7 +807,8 @@ xfs_zone_gc_write_chunk(
|
||||
{
|
||||
struct xfs_zone_gc_data *data = chunk->data;
|
||||
struct xfs_mount *mp = chunk->ip->i_mount;
|
||||
unsigned int folio_offset = chunk->bio.bi_io_vec->bv_offset;
|
||||
phys_addr_t bvec_paddr =
|
||||
bvec_phys(bio_first_bvec_all(&chunk->bio));
|
||||
struct xfs_gc_bio *split_chunk;
|
||||
|
||||
if (chunk->bio.bi_status)
|
||||
@@ -822,7 +823,7 @@ xfs_zone_gc_write_chunk(
|
||||
|
||||
bio_reset(&chunk->bio, mp->m_rtdev_targp->bt_bdev, REQ_OP_WRITE);
|
||||
bio_add_folio_nofail(&chunk->bio, chunk->scratch->folio, chunk->len,
|
||||
folio_offset);
|
||||
offset_in_folio(chunk->scratch->folio, bvec_paddr));
|
||||
|
||||
while ((split_chunk = xfs_zone_gc_split_write(data, chunk)))
|
||||
xfs_zone_gc_submit_write(data, split_chunk);
|
||||
|
||||
Reference in New Issue
Block a user