mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-11-28 14:42:16 +00:00
[XFS] Fix callers of xfs_iozero() to zero the correct range.
The problem is the two callers of xfs_iozero() are rounding out the range to be zeroed to the end of a fsb and in some cases this extends past the new eof. The call to commit_write() in xfs_iozero() will cause the Linux inode's file size to be set too high. SGI-PV: 960788 SGI-Modid: xfs-linux-melb:xfs-kern:28013a Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
This commit is contained in:
parent
2823945fda
commit
6816016137
@ -134,8 +134,7 @@ STATIC int
|
||||
xfs_iozero(
|
||||
struct inode *ip, /* inode */
|
||||
loff_t pos, /* offset in file */
|
||||
size_t count, /* size of data to zero */
|
||||
loff_t end_size) /* max file size to set */
|
||||
size_t count) /* size of data to zero */
|
||||
{
|
||||
unsigned bytes;
|
||||
struct page *page;
|
||||
@ -172,8 +171,6 @@ xfs_iozero(
|
||||
if (!status) {
|
||||
pos += bytes;
|
||||
count -= bytes;
|
||||
if (pos > i_size_read(ip))
|
||||
i_size_write(ip, pos < end_size ? pos : end_size);
|
||||
}
|
||||
|
||||
unlock:
|
||||
@ -449,8 +446,8 @@ STATIC int /* error (positive) */
|
||||
xfs_zero_last_block(
|
||||
struct inode *ip,
|
||||
xfs_iocore_t *io,
|
||||
xfs_fsize_t isize,
|
||||
xfs_fsize_t end_size)
|
||||
xfs_fsize_t offset,
|
||||
xfs_fsize_t isize)
|
||||
{
|
||||
xfs_fileoff_t last_fsb;
|
||||
xfs_mount_t *mp = io->io_mount;
|
||||
@ -459,7 +456,6 @@ xfs_zero_last_block(
|
||||
int zero_len;
|
||||
int error = 0;
|
||||
xfs_bmbt_irec_t imap;
|
||||
loff_t loff;
|
||||
|
||||
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
|
||||
|
||||
@ -494,9 +490,10 @@ xfs_zero_last_block(
|
||||
*/
|
||||
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
|
||||
|
||||
loff = XFS_FSB_TO_B(mp, last_fsb);
|
||||
zero_len = mp->m_sb.sb_blocksize - zero_offset;
|
||||
error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
|
||||
if (isize + zero_len > offset)
|
||||
zero_len = offset - isize;
|
||||
error = xfs_iozero(ip, isize, zero_len);
|
||||
|
||||
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
|
||||
ASSERT(error >= 0);
|
||||
@ -519,14 +516,15 @@ xfs_zero_eof(
|
||||
bhv_vnode_t *vp,
|
||||
xfs_iocore_t *io,
|
||||
xfs_off_t offset, /* starting I/O offset */
|
||||
xfs_fsize_t isize, /* current inode size */
|
||||
xfs_fsize_t end_size) /* terminal inode size */
|
||||
xfs_fsize_t isize) /* current inode size */
|
||||
{
|
||||
struct inode *ip = vn_to_inode(vp);
|
||||
xfs_fileoff_t start_zero_fsb;
|
||||
xfs_fileoff_t end_zero_fsb;
|
||||
xfs_fileoff_t zero_count_fsb;
|
||||
xfs_fileoff_t last_fsb;
|
||||
xfs_fileoff_t zero_off;
|
||||
xfs_fsize_t zero_len;
|
||||
xfs_mount_t *mp = io->io_mount;
|
||||
int nimaps;
|
||||
int error = 0;
|
||||
@ -540,7 +538,7 @@ xfs_zero_eof(
|
||||
* First handle zeroing the block on which isize resides.
|
||||
* We only zero a part of that block so it is handled specially.
|
||||
*/
|
||||
error = xfs_zero_last_block(ip, io, isize, end_size);
|
||||
error = xfs_zero_last_block(ip, io, offset, isize);
|
||||
if (error) {
|
||||
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
|
||||
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
|
||||
@ -601,10 +599,13 @@ xfs_zero_eof(
|
||||
*/
|
||||
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
|
||||
|
||||
error = xfs_iozero(ip,
|
||||
XFS_FSB_TO_B(mp, start_zero_fsb),
|
||||
XFS_FSB_TO_B(mp, imap.br_blockcount),
|
||||
end_size);
|
||||
zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
|
||||
zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
|
||||
|
||||
if ((zero_off + zero_len) > offset)
|
||||
zero_len = offset - zero_off;
|
||||
|
||||
error = xfs_iozero(ip, zero_off, zero_len);
|
||||
if (error) {
|
||||
goto out_lock;
|
||||
}
|
||||
@ -783,8 +784,7 @@ start:
|
||||
*/
|
||||
|
||||
if (pos > isize) {
|
||||
error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos,
|
||||
isize, pos + count);
|
||||
error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize);
|
||||
if (error) {
|
||||
xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
|
||||
goto out_unlock_mutex;
|
||||
|
@ -83,7 +83,7 @@ extern int xfs_bdstrat_cb(struct xfs_buf *);
|
||||
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
|
||||
|
||||
extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
|
||||
xfs_fsize_t, xfs_fsize_t);
|
||||
xfs_fsize_t);
|
||||
extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
|
||||
const struct iovec *, unsigned int,
|
||||
loff_t *, int, struct cred *);
|
||||
|
@ -1810,7 +1810,7 @@ xfs_igrow_start(
|
||||
* and any blocks between the old and new file sizes.
|
||||
*/
|
||||
error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
|
||||
ip->i_d.di_size, new_size);
|
||||
ip->i_d.di_size);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user