xfs: fixes for v4.0-rc2
This update contains: o ensure quota type is reset in on-disk dquots o fix missing partial EOF block data flush on truncate extension o fix transaction leak in error handling for new pnfs block layout support o add missing target_ip check to RENAME_EXCHANGE -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJU78w2AAoJEK3oKUf0dfod68IQALzcN8py4QxvmxVXf8F7+ymo PrUc/ZiP8EOS+q2wk4V0RgyoCAFA02pFjCEpWVm3PBdyfsd9DC12w7VYBlbDMO8f wApPots48NbqYVQA2+YLzC2+dgHwxLWzzJFyS6jDb/xtrVarHZtbhJU6hvl3a1gH 8RwEW+mplMmIN8Qh7vxJ2/2K+97lfS2AW0jAnnOZKCsx98XWvSgeCk+3VszwZWjD obQn2WrvlfUSSERs0z2sygx5GxR/3Wnm5LrzpiX/+gH6LdPED53o6K/tKf5ncbmF maXkYUMxvTs3tOO9ZPohtL4Zc9JarPu2U6sKmMxULOaRgZLwmk6W2cyoCbdW2du5 0ardLB89fUvGCJGMXojVtxZ6BX8IEoyhSDUX1qGF9/HFr0Rz5zIkeeqAWkj89+Cj VYvR/AmLBYwdaUPL+aHmG3P6B07u42n4650UQIVYw29rGEpxYOaBr7BAEYgyWFoM Omizf05rsz5aAxXCTjfUl+s9VsO6H0lNCjRyNs+QRIqkGf9rgxJGIAJuoh+bNNOm +WcId+5BPInuAy1YFP9Z02fe1NqIkSihTbL6daIlGIYralauXG+wyrsm9DaMsNSq VPul6HFMUwv2g5ECjvhiGZcvElOcBKcVQEUBJP3izFczP9o2i5NKcIOVFW/AxwTZ NW1qOYsLAQmD/hYpx1p2 =kTai -----END PGP SIGNATURE----- Merge tag 'xfs-for-linus-4.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs Pull xfs fixes from Dave Chinner: "These are fixes for regressions/bugs introduced in the 4.0 merge cycle and problems discovered during the merge window that need to be pushed back to stable kernels ASAP. This contains: - ensure quota type is reset in on-disk dquots - fix missing partial EOF block data flush on truncate extension - fix transaction leak in error handling for new pnfs block layout support - add missing target_ip check to RENAME_EXCHANGE" * tag 'xfs-for-linus-4.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs: xfs: cancel failed transaction in xfs_fs_commit_blocks() xfs: Ensure we have target_ip for RENAME_EXCHANGE xfs: ensure truncate forces zeroed blocks to disk xfs: Fix quota type in quota structures when reusing quota file
This commit is contained in:
commit
2aaeb784bf
|
@ -397,7 +397,8 @@ STATIC int /* error (positive) */
|
||||||
xfs_zero_last_block(
|
xfs_zero_last_block(
|
||||||
struct xfs_inode *ip,
|
struct xfs_inode *ip,
|
||||||
xfs_fsize_t offset,
|
xfs_fsize_t offset,
|
||||||
xfs_fsize_t isize)
|
xfs_fsize_t isize,
|
||||||
|
bool *did_zeroing)
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
xfs_fileoff_t last_fsb = XFS_B_TO_FSBT(mp, isize);
|
xfs_fileoff_t last_fsb = XFS_B_TO_FSBT(mp, isize);
|
||||||
|
@ -425,6 +426,7 @@ xfs_zero_last_block(
|
||||||
zero_len = mp->m_sb.sb_blocksize - zero_offset;
|
zero_len = mp->m_sb.sb_blocksize - zero_offset;
|
||||||
if (isize + zero_len > offset)
|
if (isize + zero_len > offset)
|
||||||
zero_len = offset - isize;
|
zero_len = offset - isize;
|
||||||
|
*did_zeroing = true;
|
||||||
return xfs_iozero(ip, isize, zero_len);
|
return xfs_iozero(ip, isize, zero_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +445,8 @@ int /* error (positive) */
|
||||||
xfs_zero_eof(
|
xfs_zero_eof(
|
||||||
struct xfs_inode *ip,
|
struct xfs_inode *ip,
|
||||||
xfs_off_t offset, /* starting I/O offset */
|
xfs_off_t offset, /* starting I/O offset */
|
||||||
xfs_fsize_t isize) /* current inode size */
|
xfs_fsize_t isize, /* current inode size */
|
||||||
|
bool *did_zeroing)
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
xfs_fileoff_t start_zero_fsb;
|
xfs_fileoff_t start_zero_fsb;
|
||||||
|
@ -465,7 +468,7 @@ xfs_zero_eof(
|
||||||
* We only zero a part of that block so it is handled specially.
|
* We only zero a part of that block so it is handled specially.
|
||||||
*/
|
*/
|
||||||
if (XFS_B_FSB_OFFSET(mp, isize) != 0) {
|
if (XFS_B_FSB_OFFSET(mp, isize) != 0) {
|
||||||
error = xfs_zero_last_block(ip, offset, isize);
|
error = xfs_zero_last_block(ip, offset, isize, did_zeroing);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -525,6 +528,7 @@ xfs_zero_eof(
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
*did_zeroing = true;
|
||||||
start_zero_fsb = imap.br_startoff + imap.br_blockcount;
|
start_zero_fsb = imap.br_startoff + imap.br_blockcount;
|
||||||
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
|
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
|
||||||
}
|
}
|
||||||
|
@ -567,13 +571,15 @@ restart:
|
||||||
* having to redo all checks before.
|
* having to redo all checks before.
|
||||||
*/
|
*/
|
||||||
if (*pos > i_size_read(inode)) {
|
if (*pos > i_size_read(inode)) {
|
||||||
|
bool zero = false;
|
||||||
|
|
||||||
if (*iolock == XFS_IOLOCK_SHARED) {
|
if (*iolock == XFS_IOLOCK_SHARED) {
|
||||||
xfs_rw_iunlock(ip, *iolock);
|
xfs_rw_iunlock(ip, *iolock);
|
||||||
*iolock = XFS_IOLOCK_EXCL;
|
*iolock = XFS_IOLOCK_EXCL;
|
||||||
xfs_rw_ilock(ip, *iolock);
|
xfs_rw_ilock(ip, *iolock);
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
error = xfs_zero_eof(ip, *pos, i_size_read(inode));
|
error = xfs_zero_eof(ip, *pos, i_size_read(inode), &zero);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2867,6 +2867,10 @@ xfs_rename(
|
||||||
* Handle RENAME_EXCHANGE flags
|
* Handle RENAME_EXCHANGE flags
|
||||||
*/
|
*/
|
||||||
if (flags & RENAME_EXCHANGE) {
|
if (flags & RENAME_EXCHANGE) {
|
||||||
|
if (target_ip == NULL) {
|
||||||
|
error = -EINVAL;
|
||||||
|
goto error_return;
|
||||||
|
}
|
||||||
error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
|
error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
|
||||||
target_dp, target_name, target_ip,
|
target_dp, target_name, target_ip,
|
||||||
&free_list, &first_block, spaceres);
|
&free_list, &first_block, spaceres);
|
||||||
|
|
|
@ -384,10 +384,11 @@ enum xfs_prealloc_flags {
|
||||||
XFS_PREALLOC_INVISIBLE = (1 << 4),
|
XFS_PREALLOC_INVISIBLE = (1 << 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
int xfs_update_prealloc_flags(struct xfs_inode *,
|
int xfs_update_prealloc_flags(struct xfs_inode *ip,
|
||||||
enum xfs_prealloc_flags);
|
enum xfs_prealloc_flags flags);
|
||||||
int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
|
int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset,
|
||||||
int xfs_iozero(struct xfs_inode *, loff_t, size_t);
|
xfs_fsize_t isize, bool *did_zeroing);
|
||||||
|
int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count);
|
||||||
|
|
||||||
|
|
||||||
#define IHOLD(ip) \
|
#define IHOLD(ip) \
|
||||||
|
|
|
@ -751,6 +751,7 @@ xfs_setattr_size(
|
||||||
int error;
|
int error;
|
||||||
uint lock_flags = 0;
|
uint lock_flags = 0;
|
||||||
uint commit_flags = 0;
|
uint commit_flags = 0;
|
||||||
|
bool did_zeroing = false;
|
||||||
|
|
||||||
trace_xfs_setattr(ip);
|
trace_xfs_setattr(ip);
|
||||||
|
|
||||||
|
@ -794,20 +795,16 @@ xfs_setattr_size(
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we can make the changes. Before we join the inode to the
|
* File data changes must be complete before we start the transaction to
|
||||||
* transaction, take care of the part of the truncation that must be
|
* modify the inode. This needs to be done before joining the inode to
|
||||||
* done without the inode lock. This needs to be done before joining
|
* the transaction because the inode cannot be unlocked once it is a
|
||||||
* the inode to the transaction, because the inode cannot be unlocked
|
* part of the transaction.
|
||||||
* once it is a part of the transaction.
|
*
|
||||||
|
* Start with zeroing any data block beyond EOF that we may expose on
|
||||||
|
* file extension.
|
||||||
*/
|
*/
|
||||||
if (newsize > oldsize) {
|
if (newsize > oldsize) {
|
||||||
/*
|
error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing);
|
||||||
* Do the first part of growing a file: zero any data in the
|
|
||||||
* last block that is beyond the old EOF. We need to do this
|
|
||||||
* before the inode is joined to the transaction to modify
|
|
||||||
* i_size.
|
|
||||||
*/
|
|
||||||
error = xfs_zero_eof(ip, newsize, oldsize);
|
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -817,23 +814,18 @@ xfs_setattr_size(
|
||||||
* any previous writes that are beyond the on disk EOF and the new
|
* any previous writes that are beyond the on disk EOF and the new
|
||||||
* EOF that have not been written out need to be written here. If we
|
* EOF that have not been written out need to be written here. If we
|
||||||
* do not write the data out, we expose ourselves to the null files
|
* do not write the data out, we expose ourselves to the null files
|
||||||
* problem.
|
* problem. Note that this includes any block zeroing we did above;
|
||||||
*
|
* otherwise those blocks may not be zeroed after a crash.
|
||||||
* Only flush from the on disk size to the smaller of the in memory
|
|
||||||
* file size or the new size as that's the range we really care about
|
|
||||||
* here and prevents waiting for other data not within the range we
|
|
||||||
* care about here.
|
|
||||||
*/
|
*/
|
||||||
if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) {
|
if (newsize > ip->i_d.di_size &&
|
||||||
|
(oldsize != ip->i_d.di_size || did_zeroing)) {
|
||||||
error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
|
error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
|
||||||
ip->i_d.di_size, newsize);
|
ip->i_d.di_size, newsize);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Now wait for all direct I/O to complete. */
|
||||||
* Wait for all direct I/O to complete.
|
|
||||||
*/
|
|
||||||
inode_dio_wait(inode);
|
inode_dio_wait(inode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -300,8 +300,10 @@ xfs_fs_commit_blocks(
|
||||||
|
|
||||||
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
|
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
|
||||||
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
|
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
|
||||||
if (error)
|
if (error) {
|
||||||
|
xfs_trans_cancel(tp, 0);
|
||||||
goto out_drop_iolock;
|
goto out_drop_iolock;
|
||||||
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
|
|
|
@ -836,6 +836,11 @@ xfs_qm_reset_dqcounts(
|
||||||
*/
|
*/
|
||||||
xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR,
|
xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR,
|
||||||
"xfs_quotacheck");
|
"xfs_quotacheck");
|
||||||
|
/*
|
||||||
|
* Reset type in case we are reusing group quota file for
|
||||||
|
* project quotas or vice versa
|
||||||
|
*/
|
||||||
|
ddq->d_flags = type;
|
||||||
ddq->d_bcount = 0;
|
ddq->d_bcount = 0;
|
||||||
ddq->d_icount = 0;
|
ddq->d_icount = 0;
|
||||||
ddq->d_rtbcount = 0;
|
ddq->d_rtbcount = 0;
|
||||||
|
|
Loading…
Reference in New Issue