Commit b12dd342 authored by Nathan Scott's avatar Nathan Scott

[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: default avatarNathan Scott <nathans@sgi.com>
parent 2ddd5928
...@@ -253,7 +253,8 @@ xfs_itobp( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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 { ...@@ -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); ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment