forked from Minki/linux
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: xfs: fix attr2 vs large data fork assert xfs: force buffer writeback before blocking on the ilock in inode reclaim xfs: validate acl count
This commit is contained in:
commit
ffb8fb5469
@ -42,6 +42,8 @@ xfs_acl_from_disk(struct xfs_acl *aclp)
|
|||||||
int count, i;
|
int count, i;
|
||||||
|
|
||||||
count = be32_to_cpu(aclp->acl_cnt);
|
count = be32_to_cpu(aclp->acl_cnt);
|
||||||
|
if (count > XFS_ACL_MAX_ENTRIES)
|
||||||
|
return ERR_PTR(-EFSCORRUPTED);
|
||||||
|
|
||||||
acl = posix_acl_alloc(count, GFP_KERNEL);
|
acl = posix_acl_alloc(count, GFP_KERNEL);
|
||||||
if (!acl)
|
if (!acl)
|
||||||
|
@ -110,6 +110,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
|
|||||||
/*
|
/*
|
||||||
* Query whether the requested number of additional bytes of extended
|
* Query whether the requested number of additional bytes of extended
|
||||||
* attribute space will be able to fit inline.
|
* attribute space will be able to fit inline.
|
||||||
|
*
|
||||||
* Returns zero if not, else the di_forkoff fork offset to be used in the
|
* Returns zero if not, else the di_forkoff fork offset to be used in the
|
||||||
* literal area for attribute data once the new bytes have been added.
|
* literal area for attribute data once the new bytes have been added.
|
||||||
*
|
*
|
||||||
@ -122,7 +123,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
|
|||||||
int offset;
|
int offset;
|
||||||
int minforkoff; /* lower limit on valid forkoff locations */
|
int minforkoff; /* lower limit on valid forkoff locations */
|
||||||
int maxforkoff; /* upper limit on valid forkoff locations */
|
int maxforkoff; /* upper limit on valid forkoff locations */
|
||||||
int dsize;
|
int dsize;
|
||||||
xfs_mount_t *mp = dp->i_mount;
|
xfs_mount_t *mp = dp->i_mount;
|
||||||
|
|
||||||
offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
|
offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
|
||||||
@ -136,47 +137,60 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
|
|||||||
return (offset >= minforkoff) ? minforkoff : 0;
|
return (offset >= minforkoff) ? minforkoff : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
|
/*
|
||||||
if (bytes <= XFS_IFORK_ASIZE(dp))
|
* If the requested numbers of bytes is smaller or equal to the
|
||||||
return dp->i_d.di_forkoff;
|
* current attribute fork size we can always proceed.
|
||||||
|
*
|
||||||
|
* Note that if_bytes in the data fork might actually be larger than
|
||||||
|
* the current data fork size is due to delalloc extents. In that
|
||||||
|
* case either the extent count will go down when they are converted
|
||||||
|
* to real extents, or the delalloc conversion will take care of the
|
||||||
|
* literal area rebalancing.
|
||||||
|
*/
|
||||||
|
if (bytes <= XFS_IFORK_ASIZE(dp))
|
||||||
|
return dp->i_d.di_forkoff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For attr2 we can try to move the forkoff if there is space in the
|
||||||
|
* literal area, but for the old format we are done if there is no
|
||||||
|
* space in the fixed attribute fork.
|
||||||
|
*/
|
||||||
|
if (!(mp->m_flags & XFS_MOUNT_ATTR2))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
dsize = dp->i_df.if_bytes;
|
dsize = dp->i_df.if_bytes;
|
||||||
|
|
||||||
switch (dp->i_d.di_format) {
|
switch (dp->i_d.di_format) {
|
||||||
case XFS_DINODE_FMT_EXTENTS:
|
case XFS_DINODE_FMT_EXTENTS:
|
||||||
/*
|
/*
|
||||||
* If there is no attr fork and the data fork is extents,
|
* If there is no attr fork and the data fork is extents,
|
||||||
* determine if creating the default attr fork will result
|
* determine if creating the default attr fork will result
|
||||||
* in the extents form migrating to btree. If so, the
|
* in the extents form migrating to btree. If so, the
|
||||||
* minimum offset only needs to be the space required for
|
* minimum offset only needs to be the space required for
|
||||||
* the btree root.
|
* the btree root.
|
||||||
*/
|
*/
|
||||||
if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >
|
if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >
|
||||||
xfs_default_attroffset(dp))
|
xfs_default_attroffset(dp))
|
||||||
dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
|
dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XFS_DINODE_FMT_BTREE:
|
case XFS_DINODE_FMT_BTREE:
|
||||||
/*
|
/*
|
||||||
* If have data btree then keep forkoff if we have one,
|
* If we have a data btree then keep forkoff if we have one,
|
||||||
* otherwise we are adding a new attr, so then we set
|
* otherwise we are adding a new attr, so then we set
|
||||||
* minforkoff to where the btree root can finish so we have
|
* minforkoff to where the btree root can finish so we have
|
||||||
* plenty of room for attrs
|
* plenty of room for attrs
|
||||||
*/
|
*/
|
||||||
if (dp->i_d.di_forkoff) {
|
if (dp->i_d.di_forkoff) {
|
||||||
if (offset < dp->i_d.di_forkoff)
|
if (offset < dp->i_d.di_forkoff)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
return dp->i_d.di_forkoff;
|
||||||
return dp->i_d.di_forkoff;
|
}
|
||||||
} else
|
dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
|
||||||
dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A data fork btree root must have space for at least
|
* A data fork btree root must have space for at least
|
||||||
* MINDBTPTRS key/ptr pairs if the data fork is small or empty.
|
* MINDBTPTRS key/ptr pairs if the data fork is small or empty.
|
||||||
*/
|
*/
|
||||||
minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
|
minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
|
||||||
@ -186,10 +200,10 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
|
|||||||
maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
|
maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
|
||||||
maxforkoff = maxforkoff >> 3; /* rounded down */
|
maxforkoff = maxforkoff >> 3; /* rounded down */
|
||||||
|
|
||||||
if (offset >= minforkoff && offset < maxforkoff)
|
|
||||||
return offset;
|
|
||||||
if (offset >= maxforkoff)
|
if (offset >= maxforkoff)
|
||||||
return maxforkoff;
|
return maxforkoff;
|
||||||
|
if (offset >= minforkoff)
|
||||||
|
return offset;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2835,6 +2835,27 @@ corrupt_out:
|
|||||||
return XFS_ERROR(EFSCORRUPTED);
|
return XFS_ERROR(EFSCORRUPTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xfs_promote_inode(
|
||||||
|
struct xfs_inode *ip)
|
||||||
|
{
|
||||||
|
struct xfs_buf *bp;
|
||||||
|
|
||||||
|
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
|
||||||
|
|
||||||
|
bp = xfs_incore(ip->i_mount->m_ddev_targp, ip->i_imap.im_blkno,
|
||||||
|
ip->i_imap.im_len, XBF_TRYLOCK);
|
||||||
|
if (!bp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (XFS_BUF_ISDELAYWRITE(bp)) {
|
||||||
|
xfs_buf_delwri_promote(bp);
|
||||||
|
wake_up_process(ip->i_mount->m_ddev_targp->bt_task);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfs_buf_relse(bp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a pointer to the extent record at file index idx.
|
* Return a pointer to the extent record at file index idx.
|
||||||
*/
|
*/
|
||||||
|
@ -498,6 +498,7 @@ int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
|
|||||||
void xfs_iext_realloc(xfs_inode_t *, int, int);
|
void xfs_iext_realloc(xfs_inode_t *, int, int);
|
||||||
void xfs_iunpin_wait(xfs_inode_t *);
|
void xfs_iunpin_wait(xfs_inode_t *);
|
||||||
int xfs_iflush(xfs_inode_t *, uint);
|
int xfs_iflush(xfs_inode_t *, uint);
|
||||||
|
void xfs_promote_inode(struct xfs_inode *);
|
||||||
void xfs_lock_inodes(xfs_inode_t **, int, uint);
|
void xfs_lock_inodes(xfs_inode_t **, int, uint);
|
||||||
void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
|
void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
|
||||||
|
|
||||||
|
@ -770,6 +770,17 @@ restart:
|
|||||||
if (!xfs_iflock_nowait(ip)) {
|
if (!xfs_iflock_nowait(ip)) {
|
||||||
if (!(sync_mode & SYNC_WAIT))
|
if (!(sync_mode & SYNC_WAIT))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we only have a single dirty inode in a cluster there is
|
||||||
|
* a fair chance that the AIL push may have pushed it into
|
||||||
|
* the buffer, but xfsbufd won't touch it until 30 seconds
|
||||||
|
* from now, and thus we will lock up here.
|
||||||
|
*
|
||||||
|
* Promote the inode buffer to the front of the delwri list
|
||||||
|
* and wake up xfsbufd now.
|
||||||
|
*/
|
||||||
|
xfs_promote_inode(ip);
|
||||||
xfs_iflock(ip);
|
xfs_iflock(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user