Loading fs/xfs/xfs_aops.c +43 −6 Original line number Original line Diff line number Diff line Loading @@ -982,7 +982,32 @@ xfs_vm_writepage( offset = i_size_read(inode); offset = i_size_read(inode); end_index = offset >> PAGE_CACHE_SHIFT; end_index = offset >> PAGE_CACHE_SHIFT; last_index = (offset - 1) >> PAGE_CACHE_SHIFT; last_index = (offset - 1) >> PAGE_CACHE_SHIFT; if (page->index >= end_index) { /* * The page index is less than the end_index, adjust the end_offset * to the highest offset that this page should represent. * ----------------------------------------------------- * | file mapping | <EOF> | * ----------------------------------------------------- * | Page ... | Page N-2 | Page N-1 | Page N | | * ^--------------------------------^----------|-------- * | desired writeback range | see else | * ---------------------------------^------------------| */ if (page->index < end_index) end_offset = (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT; else { /* * Check whether the page to write out is beyond or straddles * i_size or not. * ------------------------------------------------------- * | file mapping | <EOF> | * ------------------------------------------------------- * | Page ... | Page N-2 | Page N-1 | Page N | Beyond | * ^--------------------------------^-----------|--------- * | | Straddles | * ---------------------------------^-----------|--------| */ unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); /* /* Loading @@ -990,8 +1015,20 @@ xfs_vm_writepage( * truncate operation that is in progress. We must redirty the * truncate operation that is in progress. We must redirty the * page so that reclaim stops reclaiming it. Otherwise * page so that reclaim stops reclaiming it. Otherwise * xfs_vm_releasepage() is called on it and gets confused. * xfs_vm_releasepage() is called on it and gets confused. * * Note that the end_index is unsigned long, it would overflow * if the given offset is greater than 16TB on 32-bit system * and if we do check the page is fully outside i_size or not * via "if (page->index >= end_index + 1)" as "end_index + 1" * will be evaluated to 0. Hence this page will be redirtied * and be written out repeatedly which would result in an * infinite loop, the user program that perform this operation * will hang. Instead, we can verify this situation by checking * if the page to write is totally beyond the i_size or if it's * offset is just equal to the EOF. */ */ if (page->index >= end_index + 1 || offset_into_page == 0) if (page->index > end_index || (page->index == end_index && offset_into_page == 0)) goto redirty; goto redirty; /* /* Loading @@ -1003,11 +1040,11 @@ xfs_vm_writepage( * not written out to the file." * not written out to the file." */ */ zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); /* Adjust the end_offset to the end of file */ end_offset = offset; } } end_offset = min_t(unsigned long long, (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); len = 1 << inode->i_blkbits; len = 1 << inode->i_blkbits; bh = head = page_buffers(page); bh = head = page_buffers(page); Loading fs/xfs/xfs_bmap_util.c +0 −2 Original line number Original line Diff line number Diff line Loading @@ -1519,7 +1519,6 @@ xfs_collapse_file_space( while (!error && !done) { while (!error && !done) { tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); tp->t_flags |= XFS_TRANS_RESERVE; /* /* * We would need to reserve permanent block for transaction. * We would need to reserve permanent block for transaction. * This will come into picture when after shifting extent into * This will come into picture when after shifting extent into Loading @@ -1529,7 +1528,6 @@ xfs_collapse_file_space( error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); if (error) { if (error) { ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); xfs_trans_cancel(tp, 0); break; break; } } Loading fs/xfs/xfs_da_btree.c +0 −41 Original line number Original line Diff line number Diff line Loading @@ -2624,47 +2624,6 @@ xfs_da_read_buf( xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); else else xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); /* * This verification code will be moved to a CRC verification callback * function so just leave it here unchanged until then. */ { xfs_dir2_data_hdr_t *hdr = bp->b_addr; xfs_dir2_free_t *free = bp->b_addr; xfs_da_blkinfo_t *info = bp->b_addr; uint magic, magic1; struct xfs_mount *mp = dp->i_mount; magic = be16_to_cpu(info->magic); magic1 = be32_to_cpu(hdr->magic); if (unlikely( XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && (magic != XFS_DA3_NODE_MAGIC) && (magic != XFS_ATTR_LEAF_MAGIC) && (magic != XFS_ATTR3_LEAF_MAGIC) && (magic != XFS_DIR2_LEAF1_MAGIC) && (magic != XFS_DIR3_LEAF1_MAGIC) && (magic != XFS_DIR2_LEAFN_MAGIC) && (magic != XFS_DIR3_LEAFN_MAGIC) && (magic1 != XFS_DIR2_BLOCK_MAGIC) && (magic1 != XFS_DIR3_BLOCK_MAGIC) && (magic1 != XFS_DIR2_DATA_MAGIC) && (magic1 != XFS_DIR3_DATA_MAGIC) && (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)) && (free->hdr.magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)), mp, XFS_ERRTAG_DA_READ_BUF, XFS_RANDOM_DA_READ_BUF))) { trace_xfs_da_btree_corrupt(bp, _RET_IP_); XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", XFS_ERRLEVEL_LOW, mp, info); error = XFS_ERROR(EFSCORRUPTED); xfs_trans_brelse(trans, bp); goto out_free; } } *bpp = bp; *bpp = bp; out_free: out_free: if (mapp != &map) if (mapp != &map) Loading fs/xfs/xfs_ialloc.c +5 −5 Original line number Original line Diff line number Diff line Loading @@ -1437,7 +1437,7 @@ xfs_difree_inobt( struct xfs_buf *agbp, struct xfs_buf *agbp, xfs_agino_t agino, xfs_agino_t agino, struct xfs_bmap_free *flist, struct xfs_bmap_free *flist, int *delete, int *deleted, xfs_ino_t *first_ino, xfs_ino_t *first_ino, struct xfs_inobt_rec_incore *orec) struct xfs_inobt_rec_incore *orec) { { Loading Loading @@ -1497,7 +1497,7 @@ xfs_difree_inobt( if (!(mp->m_flags & XFS_MOUNT_IKEEP) && if (!(mp->m_flags & XFS_MOUNT_IKEEP) && (rec.ir_freecount == mp->m_ialloc_inos)) { (rec.ir_freecount == mp->m_ialloc_inos)) { *delete = 1; *deleted = 1; *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); /* /* Loading Loading @@ -1525,7 +1525,7 @@ xfs_difree_inobt( XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)), XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)), mp->m_ialloc_blks, flist, mp); mp->m_ialloc_blks, flist, mp); } else { } else { *delete = 0; *deleted = 0; error = xfs_inobt_update(cur, &rec); error = xfs_inobt_update(cur, &rec); if (error) { if (error) { Loading Loading @@ -1662,7 +1662,7 @@ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ xfs_ino_t inode, /* inode to be freed */ struct xfs_bmap_free *flist, /* extents to free */ struct xfs_bmap_free *flist, /* extents to free */ int *delete,/* set if inode cluster was deleted */ int *deleted,/* set if inode cluster was deleted */ xfs_ino_t *first_ino)/* first inode in deleted cluster */ xfs_ino_t *first_ino)/* first inode in deleted cluster */ { { /* REFERENCED */ /* REFERENCED */ Loading Loading @@ -1714,7 +1714,7 @@ xfs_difree( /* /* * Fix up the inode allocation btree. * Fix up the inode allocation btree. */ */ error = xfs_difree_inobt(mp, tp, agbp, agino, flist, delete, first_ino, error = xfs_difree_inobt(mp, tp, agbp, agino, flist, deleted, first_ino, &rec); &rec); if (error) if (error) goto error0; goto error0; Loading fs/xfs/xfs_ialloc.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -90,7 +90,7 @@ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ xfs_ino_t inode, /* inode to be freed */ struct xfs_bmap_free *flist, /* extents to free */ struct xfs_bmap_free *flist, /* extents to free */ int *delete, /* set if inode cluster was deleted */ int *deleted, /* set if inode cluster was deleted */ xfs_ino_t *first_ino); /* first inode in deleted cluster */ xfs_ino_t *first_ino); /* first inode in deleted cluster */ /* /* Loading Loading
fs/xfs/xfs_aops.c +43 −6 Original line number Original line Diff line number Diff line Loading @@ -982,7 +982,32 @@ xfs_vm_writepage( offset = i_size_read(inode); offset = i_size_read(inode); end_index = offset >> PAGE_CACHE_SHIFT; end_index = offset >> PAGE_CACHE_SHIFT; last_index = (offset - 1) >> PAGE_CACHE_SHIFT; last_index = (offset - 1) >> PAGE_CACHE_SHIFT; if (page->index >= end_index) { /* * The page index is less than the end_index, adjust the end_offset * to the highest offset that this page should represent. * ----------------------------------------------------- * | file mapping | <EOF> | * ----------------------------------------------------- * | Page ... | Page N-2 | Page N-1 | Page N | | * ^--------------------------------^----------|-------- * | desired writeback range | see else | * ---------------------------------^------------------| */ if (page->index < end_index) end_offset = (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT; else { /* * Check whether the page to write out is beyond or straddles * i_size or not. * ------------------------------------------------------- * | file mapping | <EOF> | * ------------------------------------------------------- * | Page ... | Page N-2 | Page N-1 | Page N | Beyond | * ^--------------------------------^-----------|--------- * | | Straddles | * ---------------------------------^-----------|--------| */ unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); /* /* Loading @@ -990,8 +1015,20 @@ xfs_vm_writepage( * truncate operation that is in progress. We must redirty the * truncate operation that is in progress. We must redirty the * page so that reclaim stops reclaiming it. Otherwise * page so that reclaim stops reclaiming it. Otherwise * xfs_vm_releasepage() is called on it and gets confused. * xfs_vm_releasepage() is called on it and gets confused. * * Note that the end_index is unsigned long, it would overflow * if the given offset is greater than 16TB on 32-bit system * and if we do check the page is fully outside i_size or not * via "if (page->index >= end_index + 1)" as "end_index + 1" * will be evaluated to 0. Hence this page will be redirtied * and be written out repeatedly which would result in an * infinite loop, the user program that perform this operation * will hang. Instead, we can verify this situation by checking * if the page to write is totally beyond the i_size or if it's * offset is just equal to the EOF. */ */ if (page->index >= end_index + 1 || offset_into_page == 0) if (page->index > end_index || (page->index == end_index && offset_into_page == 0)) goto redirty; goto redirty; /* /* Loading @@ -1003,11 +1040,11 @@ xfs_vm_writepage( * not written out to the file." * not written out to the file." */ */ zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); /* Adjust the end_offset to the end of file */ end_offset = offset; } } end_offset = min_t(unsigned long long, (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); len = 1 << inode->i_blkbits; len = 1 << inode->i_blkbits; bh = head = page_buffers(page); bh = head = page_buffers(page); Loading
fs/xfs/xfs_bmap_util.c +0 −2 Original line number Original line Diff line number Diff line Loading @@ -1519,7 +1519,6 @@ xfs_collapse_file_space( while (!error && !done) { while (!error && !done) { tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); tp->t_flags |= XFS_TRANS_RESERVE; /* /* * We would need to reserve permanent block for transaction. * We would need to reserve permanent block for transaction. * This will come into picture when after shifting extent into * This will come into picture when after shifting extent into Loading @@ -1529,7 +1528,6 @@ xfs_collapse_file_space( error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); if (error) { if (error) { ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); xfs_trans_cancel(tp, 0); break; break; } } Loading
fs/xfs/xfs_da_btree.c +0 −41 Original line number Original line Diff line number Diff line Loading @@ -2624,47 +2624,6 @@ xfs_da_read_buf( xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); else else xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); /* * This verification code will be moved to a CRC verification callback * function so just leave it here unchanged until then. */ { xfs_dir2_data_hdr_t *hdr = bp->b_addr; xfs_dir2_free_t *free = bp->b_addr; xfs_da_blkinfo_t *info = bp->b_addr; uint magic, magic1; struct xfs_mount *mp = dp->i_mount; magic = be16_to_cpu(info->magic); magic1 = be32_to_cpu(hdr->magic); if (unlikely( XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && (magic != XFS_DA3_NODE_MAGIC) && (magic != XFS_ATTR_LEAF_MAGIC) && (magic != XFS_ATTR3_LEAF_MAGIC) && (magic != XFS_DIR2_LEAF1_MAGIC) && (magic != XFS_DIR3_LEAF1_MAGIC) && (magic != XFS_DIR2_LEAFN_MAGIC) && (magic != XFS_DIR3_LEAFN_MAGIC) && (magic1 != XFS_DIR2_BLOCK_MAGIC) && (magic1 != XFS_DIR3_BLOCK_MAGIC) && (magic1 != XFS_DIR2_DATA_MAGIC) && (magic1 != XFS_DIR3_DATA_MAGIC) && (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)) && (free->hdr.magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)), mp, XFS_ERRTAG_DA_READ_BUF, XFS_RANDOM_DA_READ_BUF))) { trace_xfs_da_btree_corrupt(bp, _RET_IP_); XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", XFS_ERRLEVEL_LOW, mp, info); error = XFS_ERROR(EFSCORRUPTED); xfs_trans_brelse(trans, bp); goto out_free; } } *bpp = bp; *bpp = bp; out_free: out_free: if (mapp != &map) if (mapp != &map) Loading
fs/xfs/xfs_ialloc.c +5 −5 Original line number Original line Diff line number Diff line Loading @@ -1437,7 +1437,7 @@ xfs_difree_inobt( struct xfs_buf *agbp, struct xfs_buf *agbp, xfs_agino_t agino, xfs_agino_t agino, struct xfs_bmap_free *flist, struct xfs_bmap_free *flist, int *delete, int *deleted, xfs_ino_t *first_ino, xfs_ino_t *first_ino, struct xfs_inobt_rec_incore *orec) struct xfs_inobt_rec_incore *orec) { { Loading Loading @@ -1497,7 +1497,7 @@ xfs_difree_inobt( if (!(mp->m_flags & XFS_MOUNT_IKEEP) && if (!(mp->m_flags & XFS_MOUNT_IKEEP) && (rec.ir_freecount == mp->m_ialloc_inos)) { (rec.ir_freecount == mp->m_ialloc_inos)) { *delete = 1; *deleted = 1; *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); /* /* Loading Loading @@ -1525,7 +1525,7 @@ xfs_difree_inobt( XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)), XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)), mp->m_ialloc_blks, flist, mp); mp->m_ialloc_blks, flist, mp); } else { } else { *delete = 0; *deleted = 0; error = xfs_inobt_update(cur, &rec); error = xfs_inobt_update(cur, &rec); if (error) { if (error) { Loading Loading @@ -1662,7 +1662,7 @@ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ xfs_ino_t inode, /* inode to be freed */ struct xfs_bmap_free *flist, /* extents to free */ struct xfs_bmap_free *flist, /* extents to free */ int *delete,/* set if inode cluster was deleted */ int *deleted,/* set if inode cluster was deleted */ xfs_ino_t *first_ino)/* first inode in deleted cluster */ xfs_ino_t *first_ino)/* first inode in deleted cluster */ { { /* REFERENCED */ /* REFERENCED */ Loading Loading @@ -1714,7 +1714,7 @@ xfs_difree( /* /* * Fix up the inode allocation btree. * Fix up the inode allocation btree. */ */ error = xfs_difree_inobt(mp, tp, agbp, agino, flist, delete, first_ino, error = xfs_difree_inobt(mp, tp, agbp, agino, flist, deleted, first_ino, &rec); &rec); if (error) if (error) goto error0; goto error0; Loading
fs/xfs/xfs_ialloc.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -90,7 +90,7 @@ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ xfs_ino_t inode, /* inode to be freed */ struct xfs_bmap_free *flist, /* extents to free */ struct xfs_bmap_free *flist, /* extents to free */ int *delete, /* set if inode cluster was deleted */ int *deleted, /* set if inode cluster was deleted */ xfs_ino_t *first_ino); /* first inode in deleted cluster */ xfs_ino_t *first_ino); /* first inode in deleted cluster */ /* /* Loading