Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b12dd342 authored by Nathan Scott's avatar Nathan Scott
Browse files

[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
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -253,7 +253,8 @@ xfs_itobp(
	xfs_inode_t	*ip,
	xfs_dinode_t	**dipp,
	xfs_buf_t	**bpp,
	xfs_daddr_t	bno)
	xfs_daddr_t	bno,
	uint		imap_flags)
{
	xfs_buf_t	*bp;
	int		error;
@@ -269,10 +270,9 @@ xfs_itobp(
		 * inode on disk.
		 */
		imap.im_blkno = bno;
		error = xfs_imap(mp, tp, ip->i_ino, &imap, XFS_IMAP_LOOKUP);
		if (error != 0) {
		if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
					XFS_IMAP_LOOKUP | imap_flags)))
			return error;
		}

		/*
		 * 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.
	 */
#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
	ni = 1;
	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
#endif
	for (i = 0; i < ni; i++) {
		int		di_ok;
@@ -868,9 +869,8 @@ xfs_iread(
	 * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
	 * know that this is a new incore inode.
	 */
	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno);

	if (error != 0) {
	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
	if (error) {
		kmem_zone_free(xfs_inode_zone, ip);
		return error;
	}
@@ -1895,7 +1895,7 @@ xfs_iunlink(
		 * Here we put the head pointer into our next pointer,
		 * 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) {
			return error;
		}
@@ -2004,7 +2004,7 @@ xfs_iunlink_remove(
		 * of dealing with the buffer when there is no need to
		 * change it.
		 */
		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
		if (error) {
			cmn_err(CE_WARN,
				"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
		 * 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) {
			cmn_err(CE_WARN,
				"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.
	 */
	error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0);
	if (error != 0) {
	error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
	if (error) {
		xfs_ifunlock(ip);
		return error;
	}
+4 −3
Original line number Diff line number Diff line
@@ -95,9 +95,10 @@ typedef struct xfs_ifork {
#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_BULKSTAT	0x2

#ifdef __KERNEL__
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 *,
			  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,
			  xfs_inode_t **, xfs_daddr_t);
int		xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
+4 −1
Original line number Diff line number Diff line
@@ -562,7 +562,8 @@ xfs_bulkstat(
						if (bp)
							xfs_buf_relse(bp);
						error = xfs_itobp(mp, NULL, ip,
								  &dip, &bp, bno);
								&dip, &bp, bno,
								XFS_IMAP_BULKSTAT);
						if (!error)
							clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
						kmem_zone_free(xfs_inode_zone, ip);
@@ -570,6 +571,8 @@ xfs_bulkstat(
								   mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
								   XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
							bp = NULL;
							ubleft = 0;
							rval = error;
							break;
						}
					}
+1 −1
Original line number Diff line number Diff line
@@ -3249,7 +3249,7 @@ xlog_recover_process_iunlinks(
					 * next inode in the bucket.
					 */
					error = xfs_itobp(mp, NULL, ip, &dip,
							&ibp, 0);
							&ibp, 0, 0);
					ASSERT(error || (dip != NULL));
				}

+1 −1
Original line number Diff line number Diff line
@@ -1229,7 +1229,7 @@ xfs_sync_inodes(
					xfs_iunlock(ip, XFS_ILOCK_SHARED);

					error = xfs_itobp(mp, NULL, ip,
							  &dip, &bp, 0);
							  &dip, &bp, 0, 0);
					if (!error) {
						xfs_buf_relse(bp);
					} else {