[XFS] Fix an infinite loop issue in bulkstat when a corrupt inode is
detected. Thanks to Roger Willcocks. SGI-PV: 951054 SGI-Modid: xfs-linux-melb:xfs-kern:25477a Signed-off-by: Nathan Scott <nathans@sgi.com>
This commit is contained in:
parent
2ddd5928d0
commit
b12dd34298
|
@ -253,7 +253,8 @@ xfs_itobp(
|
||||||
xfs_inode_t *ip,
|
xfs_inode_t *ip,
|
||||||
xfs_dinode_t **dipp,
|
xfs_dinode_t **dipp,
|
||||||
xfs_buf_t **bpp,
|
xfs_buf_t **bpp,
|
||||||
xfs_daddr_t bno)
|
xfs_daddr_t bno,
|
||||||
|
uint imap_flags)
|
||||||
{
|
{
|
||||||
xfs_buf_t *bp;
|
xfs_buf_t *bp;
|
||||||
int error;
|
int error;
|
||||||
|
@ -269,10 +270,9 @@ xfs_itobp(
|
||||||
* inode on disk.
|
* inode on disk.
|
||||||
*/
|
*/
|
||||||
imap.im_blkno = bno;
|
imap.im_blkno = bno;
|
||||||
error = xfs_imap(mp, tp, ip->i_ino, &imap, XFS_IMAP_LOOKUP);
|
if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
|
||||||
if (error != 0) {
|
XFS_IMAP_LOOKUP | imap_flags)))
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the inode number maps to a block outside the bounds
|
* If the inode number maps to a block outside the bounds
|
||||||
|
@ -336,9 +336,10 @@ xfs_itobp(
|
||||||
* (if DEBUG kernel) or the first inode in the buffer, otherwise.
|
* (if DEBUG kernel) or the first inode in the buffer, otherwise.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog;
|
ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
|
||||||
|
(BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
|
||||||
#else
|
#else
|
||||||
ni = 1;
|
ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < ni; i++) {
|
for (i = 0; i < ni; i++) {
|
||||||
int di_ok;
|
int di_ok;
|
||||||
|
@ -868,9 +869,8 @@ xfs_iread(
|
||||||
* return NULL as well. Set i_blkno to 0 so that xfs_itobp() will
|
* return NULL as well. Set i_blkno to 0 so that xfs_itobp() will
|
||||||
* know that this is a new incore inode.
|
* know that this is a new incore inode.
|
||||||
*/
|
*/
|
||||||
error = xfs_itobp(mp, tp, ip, &dip, &bp, bno);
|
error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
|
||||||
|
if (error) {
|
||||||
if (error != 0) {
|
|
||||||
kmem_zone_free(xfs_inode_zone, ip);
|
kmem_zone_free(xfs_inode_zone, ip);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -1895,7 +1895,7 @@ xfs_iunlink(
|
||||||
* Here we put the head pointer into our next pointer,
|
* Here we put the head pointer into our next pointer,
|
||||||
* and then we fall through to point the head at us.
|
* and then we fall through to point the head at us.
|
||||||
*/
|
*/
|
||||||
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
|
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -2004,7 +2004,7 @@ xfs_iunlink_remove(
|
||||||
* of dealing with the buffer when there is no need to
|
* of dealing with the buffer when there is no need to
|
||||||
* change it.
|
* change it.
|
||||||
*/
|
*/
|
||||||
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
|
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
cmn_err(CE_WARN,
|
cmn_err(CE_WARN,
|
||||||
"xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
|
"xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
|
||||||
|
@ -2066,7 +2066,7 @@ xfs_iunlink_remove(
|
||||||
* Now last_ibp points to the buffer previous to us on
|
* Now last_ibp points to the buffer previous to us on
|
||||||
* the unlinked list. Pull us from the list.
|
* the unlinked list. Pull us from the list.
|
||||||
*/
|
*/
|
||||||
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
|
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
cmn_err(CE_WARN,
|
cmn_err(CE_WARN,
|
||||||
"xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
|
"xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
|
||||||
|
@ -3023,8 +3023,8 @@ xfs_iflush(
|
||||||
/*
|
/*
|
||||||
* Get the buffer containing the on-disk inode.
|
* Get the buffer containing the on-disk inode.
|
||||||
*/
|
*/
|
||||||
error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0);
|
error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
|
||||||
if (error != 0) {
|
if (error) {
|
||||||
xfs_ifunlock(ip);
|
xfs_ifunlock(ip);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,9 +95,10 @@ typedef struct xfs_ifork {
|
||||||
#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */
|
#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for xfs_imap() and xfs_dilocate().
|
* Flags for xfs_itobp(), xfs_imap() and xfs_dilocate().
|
||||||
*/
|
*/
|
||||||
#define XFS_IMAP_LOOKUP 0x1
|
#define XFS_IMAP_LOOKUP 0x1
|
||||||
|
#define XFS_IMAP_BULKSTAT 0x2
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
struct bhv_desc;
|
struct bhv_desc;
|
||||||
|
@ -421,7 +422,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
|
||||||
*/
|
*/
|
||||||
int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
|
int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
|
||||||
xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
|
xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
|
||||||
xfs_daddr_t);
|
xfs_daddr_t, uint);
|
||||||
int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
|
int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
|
||||||
xfs_inode_t **, xfs_daddr_t);
|
xfs_inode_t **, xfs_daddr_t);
|
||||||
int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
|
int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
|
||||||
|
|
|
@ -562,7 +562,8 @@ xfs_bulkstat(
|
||||||
if (bp)
|
if (bp)
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
error = xfs_itobp(mp, NULL, ip,
|
error = xfs_itobp(mp, NULL, ip,
|
||||||
&dip, &bp, bno);
|
&dip, &bp, bno,
|
||||||
|
XFS_IMAP_BULKSTAT);
|
||||||
if (!error)
|
if (!error)
|
||||||
clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
|
clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
|
||||||
kmem_zone_free(xfs_inode_zone, ip);
|
kmem_zone_free(xfs_inode_zone, ip);
|
||||||
|
@ -570,6 +571,8 @@ xfs_bulkstat(
|
||||||
mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
|
mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
|
||||||
XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
|
XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
|
||||||
bp = NULL;
|
bp = NULL;
|
||||||
|
ubleft = 0;
|
||||||
|
rval = error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3249,7 +3249,7 @@ xlog_recover_process_iunlinks(
|
||||||
* next inode in the bucket.
|
* next inode in the bucket.
|
||||||
*/
|
*/
|
||||||
error = xfs_itobp(mp, NULL, ip, &dip,
|
error = xfs_itobp(mp, NULL, ip, &dip,
|
||||||
&ibp, 0);
|
&ibp, 0, 0);
|
||||||
ASSERT(error || (dip != NULL));
|
ASSERT(error || (dip != NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1229,7 +1229,7 @@ xfs_sync_inodes(
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
|
|
||||||
error = xfs_itobp(mp, NULL, ip,
|
error = xfs_itobp(mp, NULL, ip,
|
||||||
&dip, &bp, 0);
|
&dip, &bp, 0, 0);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue