aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2006-03-17 01:26:04 -0500
committerNathan Scott <nathans@sgi.com>2006-03-17 01:26:04 -0500
commitb12dd34298cf0cff9f337f667045335140873039 (patch)
tree0f2ef353bc17f247e538a28137a0a3f8ad3b5e0e /fs/xfs
parent2ddd5928d01ca8eb49f55166411b64a5844a8959 (diff)
[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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_inode.c28
-rw-r--r--fs/xfs/xfs_inode.h7
-rw-r--r--fs/xfs/xfs_itable.c5
-rw-r--r--fs/xfs/xfs_log_recover.c2
-rw-r--r--fs/xfs/xfs_vfsops.c2
5 files changed, 24 insertions, 20 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 86a8451d10fc..b1e95707e7cf 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -253,7 +253,8 @@ xfs_itobp(
253 xfs_inode_t *ip, 253 xfs_inode_t *ip,
254 xfs_dinode_t **dipp, 254 xfs_dinode_t **dipp,
255 xfs_buf_t **bpp, 255 xfs_buf_t **bpp,
256 xfs_daddr_t bno) 256 xfs_daddr_t bno,
257 uint imap_flags)
257{ 258{
258 xfs_buf_t *bp; 259 xfs_buf_t *bp;
259 int error; 260 int error;
@@ -269,10 +270,9 @@ xfs_itobp(
269 * inode on disk. 270 * inode on disk.
270 */ 271 */
271 imap.im_blkno = bno; 272 imap.im_blkno = bno;
272 error = xfs_imap(mp, tp, ip->i_ino, &imap, XFS_IMAP_LOOKUP); 273 if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
273 if (error != 0) { 274 XFS_IMAP_LOOKUP | imap_flags)))
274 return error; 275 return error;
275 }
276 276
277 /* 277 /*
278 * If the inode number maps to a block outside the bounds 278 * If the inode number maps to a block outside the bounds
@@ -336,9 +336,10 @@ xfs_itobp(
336 * (if DEBUG kernel) or the first inode in the buffer, otherwise. 336 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
337 */ 337 */
338#ifdef DEBUG 338#ifdef DEBUG
339 ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog; 339 ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
340 (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
340#else 341#else
341 ni = 1; 342 ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
342#endif 343#endif
343 for (i = 0; i < ni; i++) { 344 for (i = 0; i < ni; i++) {
344 int di_ok; 345 int di_ok;
@@ -868,9 +869,8 @@ xfs_iread(
868 * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will 869 * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will
869 * know that this is a new incore inode. 870 * know that this is a new incore inode.
870 */ 871 */
871 error = xfs_itobp(mp, tp, ip, &dip, &bp, bno); 872 error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
872 873 if (error) {
873 if (error != 0) {
874 kmem_zone_free(xfs_inode_zone, ip); 874 kmem_zone_free(xfs_inode_zone, ip);
875 return error; 875 return error;
876 } 876 }
@@ -1895,7 +1895,7 @@ xfs_iunlink(
1895 * Here we put the head pointer into our next pointer, 1895 * Here we put the head pointer into our next pointer,
1896 * and then we fall through to point the head at us. 1896 * and then we fall through to point the head at us.
1897 */ 1897 */
1898 error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); 1898 error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
1899 if (error) { 1899 if (error) {
1900 return error; 1900 return error;
1901 } 1901 }
@@ -2004,7 +2004,7 @@ xfs_iunlink_remove(
2004 * of dealing with the buffer when there is no need to 2004 * of dealing with the buffer when there is no need to
2005 * change it. 2005 * change it.
2006 */ 2006 */
2007 error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); 2007 error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
2008 if (error) { 2008 if (error) {
2009 cmn_err(CE_WARN, 2009 cmn_err(CE_WARN,
2010 "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", 2010 "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
@@ -2066,7 +2066,7 @@ xfs_iunlink_remove(
2066 * Now last_ibp points to the buffer previous to us on 2066 * Now last_ibp points to the buffer previous to us on
2067 * the unlinked list. Pull us from the list. 2067 * the unlinked list. Pull us from the list.
2068 */ 2068 */
2069 error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); 2069 error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
2070 if (error) { 2070 if (error) {
2071 cmn_err(CE_WARN, 2071 cmn_err(CE_WARN,
2072 "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", 2072 "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
@@ -3023,8 +3023,8 @@ xfs_iflush(
3023 /* 3023 /*
3024 * Get the buffer containing the on-disk inode. 3024 * Get the buffer containing the on-disk inode.
3025 */ 3025 */
3026 error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0); 3026 error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
3027 if (error != 0) { 3027 if (error) {
3028 xfs_ifunlock(ip); 3028 xfs_ifunlock(ip);
3029 return error; 3029 return error;
3030 } 3030 }
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 006396764cbc..39ef9c36ea55 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -95,9 +95,10 @@ typedef struct xfs_ifork {
95#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */ 95#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */
96 96
97/* 97/*
98 * Flags for xfs_imap() and xfs_dilocate(). 98 * Flags for xfs_itobp(), xfs_imap() and xfs_dilocate().
99 */ 99 */
100#define XFS_IMAP_LOOKUP 0x1 100#define XFS_IMAP_LOOKUP 0x1
101#define XFS_IMAP_BULKSTAT 0x2
101 102
102#ifdef __KERNEL__ 103#ifdef __KERNEL__
103struct bhv_desc; 104struct bhv_desc;
@@ -421,7 +422,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
421 */ 422 */
422int xfs_itobp(struct xfs_mount *, struct xfs_trans *, 423int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
423 xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **, 424 xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
424 xfs_daddr_t); 425 xfs_daddr_t, uint);
425int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, 426int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
426 xfs_inode_t **, xfs_daddr_t); 427 xfs_inode_t **, xfs_daddr_t);
427int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int); 428int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index c59450e1be40..32247b6bfee7 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -562,7 +562,8 @@ xfs_bulkstat(
562 if (bp) 562 if (bp)
563 xfs_buf_relse(bp); 563 xfs_buf_relse(bp);
564 error = xfs_itobp(mp, NULL, ip, 564 error = xfs_itobp(mp, NULL, ip,
565 &dip, &bp, bno); 565 &dip, &bp, bno,
566 XFS_IMAP_BULKSTAT);
566 if (!error) 567 if (!error)
567 clustidx = ip->i_boffset / mp->m_sb.sb_inodesize; 568 clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
568 kmem_zone_free(xfs_inode_zone, ip); 569 kmem_zone_free(xfs_inode_zone, ip);
@@ -570,6 +571,8 @@ xfs_bulkstat(
570 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK, 571 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
571 XFS_RANDOM_BULKSTAT_READ_CHUNK)) { 572 XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
572 bp = NULL; 573 bp = NULL;
574 ubleft = 0;
575 rval = error;
573 break; 576 break;
574 } 577 }
575 } 578 }
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 7d46cbd6a07a..add13f507ed2 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3249,7 +3249,7 @@ xlog_recover_process_iunlinks(
3249 * next inode in the bucket. 3249 * next inode in the bucket.
3250 */ 3250 */
3251 error = xfs_itobp(mp, NULL, ip, &dip, 3251 error = xfs_itobp(mp, NULL, ip, &dip,
3252 &ibp, 0); 3252 &ibp, 0, 0);
3253 ASSERT(error || (dip != NULL)); 3253 ASSERT(error || (dip != NULL));
3254 } 3254 }
3255 3255
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 5dd84fe609cc..811a4261fa2c 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1229,7 +1229,7 @@ xfs_sync_inodes(
1229 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1229 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1230 1230
1231 error = xfs_itobp(mp, NULL, ip, 1231 error = xfs_itobp(mp, NULL, ip,
1232 &dip, &bp, 0); 1232 &dip, &bp, 0, 0);
1233 if (!error) { 1233 if (!error) {
1234 xfs_buf_relse(bp); 1234 xfs_buf_relse(bp);
1235 } else { 1235 } else {