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(
|
||||
struct xfs_inode *ip,
|
||||
xfs_fsize_t offset,
|
||||
xfs_fsize_t isize)
|
||||
xfs_fsize_t isize,
|
||||
bool *did_zeroing)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
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;
|
||||
if (isize + zero_len > offset)
|
||||
zero_len = offset - isize;
|
||||
*did_zeroing = true;
|
||||
return xfs_iozero(ip, isize, zero_len);
|
||||
}
|
||||
|
||||
|
@ -443,7 +445,8 @@ int /* error (positive) */
|
|||
xfs_zero_eof(
|
||||
struct xfs_inode *ip,
|
||||
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;
|
||||
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.
|
||||
*/
|
||||
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)
|
||||
return error;
|
||||
}
|
||||
|
@ -525,6 +528,7 @@ xfs_zero_eof(
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
*did_zeroing = true;
|
||||
start_zero_fsb = imap.br_startoff + imap.br_blockcount;
|
||||
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
|
||||
}
|
||||
|
@ -567,13 +571,15 @@ restart:
|
|||
* having to redo all checks before.
|
||||
*/
|
||||
if (*pos > i_size_read(inode)) {
|
||||
bool zero = false;
|
||||
|
||||
if (*iolock == XFS_IOLOCK_SHARED) {
|
||||
xfs_rw_iunlock(ip, *iolock);
|
||||
*iolock = XFS_IOLOCK_EXCL;
|
||||
xfs_rw_ilock(ip, *iolock);
|
||||
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)
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -2867,6 +2867,10 @@ xfs_rename(
|
|||
* Handle RENAME_EXCHANGE flags
|
||||
*/
|
||||
if (flags & RENAME_EXCHANGE) {
|
||||
if (target_ip == NULL) {
|
||||
error = -EINVAL;
|
||||
goto error_return;
|
||||
}
|
||||
error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
|
||||
target_dp, target_name, target_ip,
|
||||
&free_list, &first_block, spaceres);
|
||||
|
|
|
@ -384,10 +384,11 @@ enum xfs_prealloc_flags {
|
|||
XFS_PREALLOC_INVISIBLE = (1 << 4),
|
||||
};
|
||||
|
||||
int xfs_update_prealloc_flags(struct xfs_inode *,
|
||||
enum xfs_prealloc_flags);
|
||||
int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
|
||||
int xfs_iozero(struct xfs_inode *, loff_t, size_t);
|
||||
int xfs_update_prealloc_flags(struct xfs_inode *ip,
|
||||
enum xfs_prealloc_flags flags);
|
||||
int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset,
|
||||
xfs_fsize_t isize, bool *did_zeroing);
|
||||
int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count);
|
||||
|
||||
|
||||
#define IHOLD(ip) \
|
||||
|
|
|
@ -751,6 +751,7 @@ xfs_setattr_size(
|
|||
int error;
|
||||
uint lock_flags = 0;
|
||||
uint commit_flags = 0;
|
||||
bool did_zeroing = false;
|
||||
|
||||
trace_xfs_setattr(ip);
|
||||
|
||||
|
@ -794,20 +795,16 @@ xfs_setattr_size(
|
|||
return error;
|
||||
|
||||
/*
|
||||
* Now we can make the changes. Before we join the inode to the
|
||||
* transaction, take care of the part of the truncation that must be
|
||||
* done without the inode lock. This needs to be done before joining
|
||||
* the inode to the transaction, because the inode cannot be unlocked
|
||||
* once it is a part of the transaction.
|
||||
* File data changes must be complete before we start the transaction to
|
||||
* modify the inode. This needs to be done before joining the inode to
|
||||
* the transaction because the inode cannot be unlocked 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) {
|
||||
/*
|
||||
* 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);
|
||||
error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
@ -817,23 +814,18 @@ xfs_setattr_size(
|
|||
* 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
|
||||
* do not write the data out, we expose ourselves to the null files
|
||||
* problem.
|
||||
*
|
||||
* 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.
|
||||
* problem. Note that this includes any block zeroing we did above;
|
||||
* otherwise those blocks may not be zeroed after a crash.
|
||||
*/
|
||||
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,
|
||||
ip->i_d.di_size, newsize);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for all direct I/O to complete.
|
||||
*/
|
||||
/* Now wait for all direct I/O to complete. */
|
||||
inode_dio_wait(inode);
|
||||
|
||||
/*
|
||||
|
|
|
@ -300,8 +300,10 @@ xfs_fs_commit_blocks(
|
|||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
|
||||
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;
|
||||
}
|
||||
|
||||
xfs_ilock(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_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_icount = 0;
|
||||
ddq->d_rtbcount = 0;
|
||||
|
|
Loading…
Reference in New Issue