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

Commit ab048fb1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://oss.sgi.com:8090/xfs/linux-2.6:
  [XFS] Don't do I/O beyond eof when unreserving space
  [XFS] Fix use-after-free with buffers
  [XFS] Prevent lockdep false positives when locking two inodes.
  [XFS] Fix barrier status change detection.
  [XFS] Prevent direct I/O from mapping extents beyond eof
  [XFS] Fix regression introduced by remount fixup
  [XFS] Move memory allocations for log tracing out of the critical path
parents 5a0cd4eb 2fd6f6ec
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1338,6 +1338,10 @@ __xfs_get_blocks(
	offset = (xfs_off_t)iblock << inode->i_blkbits;
	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
	size = bh_result->b_size;

	if (!create && direct && offset >= i_size_read(inode))
		return 0;

	error = xfs_iomap(XFS_I(inode), offset, size,
			     create ? flags : BMAPI_READ, &iomap, &niomap);
	if (error)
+20 −0
Original line number Diff line number Diff line
@@ -1302,9 +1302,29 @@ xfs_fs_remount(
			mp->m_flags &= ~XFS_MOUNT_BARRIER;
			break;
		default:
			/*
			 * Logically we would return an error here to prevent
			 * users from believing they might have changed
			 * mount options using remount which can't be changed.
			 *
			 * But unfortunately mount(8) adds all options from
			 * mtab and fstab to the mount arguments in some cases
			 * so we can't blindly reject options, but have to
			 * check for each specified option if it actually
			 * differs from the currently set option and only
			 * reject it if that's the case.
			 *
			 * Until that is implemented we return success for
			 * every remount request, and silently ignore all
			 * options that we can't actually change.
			 */
#if 0
			printk(KERN_INFO
	"XFS: mount option \"%s\" not supported for remount\n", p);
			return -EINVAL;
#else
			return 0;
#endif
		}
	}

+20 −24
Original line number Diff line number Diff line
@@ -732,6 +732,7 @@ xfs_buf_item_init(
	bip->bli_item.li_ops = &xfs_buf_item_ops;
	bip->bli_item.li_mountp = mp;
	bip->bli_buf = bp;
	xfs_buf_hold(bp);
	bip->bli_format.blf_type = XFS_LI_BUF;
	bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp);
	bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp));
@@ -867,6 +868,21 @@ xfs_buf_item_dirty(
	return (bip->bli_flags & XFS_BLI_DIRTY);
}

STATIC void
xfs_buf_item_free(
	xfs_buf_log_item_t	*bip)
{
#ifdef XFS_TRANS_DEBUG
	kmem_free(bip->bli_orig);
	kmem_free(bip->bli_logged);
#endif /* XFS_TRANS_DEBUG */

#ifdef XFS_BLI_TRACE
	ktrace_free(bip->bli_trace);
#endif
	kmem_zone_free(xfs_buf_item_zone, bip);
}

/*
 * This is called when the buf log item is no longer needed.  It should
 * free the buf log item associated with the given buffer and clear
@@ -887,18 +903,8 @@ xfs_buf_item_relse(
	    (XFS_BUF_IODONE_FUNC(bp) != NULL)) {
		XFS_BUF_CLR_IODONE_FUNC(bp);
	}

#ifdef XFS_TRANS_DEBUG
	kmem_free(bip->bli_orig);
	bip->bli_orig = NULL;
	kmem_free(bip->bli_logged);
	bip->bli_logged = NULL;
#endif /* XFS_TRANS_DEBUG */

#ifdef XFS_BLI_TRACE
	ktrace_free(bip->bli_trace);
#endif
	kmem_zone_free(xfs_buf_item_zone, bip);
	xfs_buf_rele(bp);
	xfs_buf_item_free(bip);
}


@@ -1120,6 +1126,7 @@ xfs_buf_iodone(

	ASSERT(bip->bli_buf == bp);

	xfs_buf_rele(bp);
	mp = bip->bli_item.li_mountp;

	/*
@@ -1136,18 +1143,7 @@ xfs_buf_iodone(
	 * xfs_trans_delete_ail() drops the AIL lock.
	 */
	xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip);

#ifdef XFS_TRANS_DEBUG
	kmem_free(bip->bli_orig);
	bip->bli_orig = NULL;
	kmem_free(bip->bli_logged);
	bip->bli_logged = NULL;
#endif /* XFS_TRANS_DEBUG */

#ifdef XFS_BLI_TRACE
	ktrace_free(bip->bli_trace);
#endif
	kmem_zone_free(xfs_buf_item_zone, bip);
	xfs_buf_item_free(bip);
}

#if defined(XFS_BLI_TRACE)
+8 −1
Original line number Diff line number Diff line
@@ -149,7 +149,14 @@ xfs_swap_extents(

	sbp = &sxp->sx_stat;

	xfs_lock_two_inodes(ip, tip, lock_flags);
	/*
	 * we have to do two separate lock calls here to keep lockdep
	 * happy. If we try to get all the locks in one call, lock will
	 * report false positives when we drop the ILOCK and regain them
	 * below.
	 */
	xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL);
	xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
	locked = 1;

	/* Verify that both files have the same format */
+41 −21
Original line number Diff line number Diff line
@@ -124,16 +124,27 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
STATIC int	xlog_iclogs_empty(xlog_t *log);

#if defined(XFS_LOG_TRACE)

#define XLOG_TRACE_LOGGRANT_SIZE	2048
#define XLOG_TRACE_ICLOG_SIZE		256

void
xlog_trace_loggrant_alloc(xlog_t *log)
{
	log->l_grant_trace = ktrace_alloc(XLOG_TRACE_LOGGRANT_SIZE, KM_NOFS);
}

void
xlog_trace_loggrant_dealloc(xlog_t *log)
{
	ktrace_free(log->l_grant_trace);
}

void
xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
{
	unsigned long cnts;

	if (!log->l_grant_trace) {
		log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP);
		if (!log->l_grant_trace)
			return;
	}
	/* ticket counts are 1 byte each */
	cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8;

@@ -156,11 +167,21 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
		     (void *)((unsigned long)tic->t_unit_res));
}

void
xlog_trace_iclog_alloc(xlog_in_core_t *iclog)
{
	iclog->ic_trace = ktrace_alloc(XLOG_TRACE_ICLOG_SIZE, KM_NOFS);
}

void
xlog_trace_iclog_dealloc(xlog_in_core_t *iclog)
{
	ktrace_free(iclog->ic_trace);
}

void
xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
{
	if (!iclog->ic_trace)
		iclog->ic_trace = ktrace_alloc(256, KM_NOFS);
	ktrace_enter(iclog->ic_trace,
		     (void *)((unsigned long)state),
		     (void *)((unsigned long)current_pid()),
@@ -170,8 +191,15 @@ xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
		     (void *)NULL, (void *)NULL);
}
#else

#define	xlog_trace_loggrant_alloc(log)
#define	xlog_trace_loggrant_dealloc(log)
#define	xlog_trace_loggrant(log,tic,string)

#define	xlog_trace_iclog_alloc(iclog)
#define	xlog_trace_iclog_dealloc(iclog)
#define	xlog_trace_iclog(iclog,state)

#endif /* XFS_LOG_TRACE */


@@ -1009,7 +1037,7 @@ xlog_iodone(xfs_buf_t *bp)
	 * layer, it means the underlyin device no longer supports
	 * barrier I/O. Warn loudly and turn off barriers.
	 */
	if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) {
	if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) {
		l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
		xfs_fs_cmn_err(CE_WARN, l->l_mp,
				"xlog_iodone: Barriers are no longer supported"
@@ -1231,6 +1259,7 @@ xlog_alloc_log(xfs_mount_t *mp,
	spin_lock_init(&log->l_grant_lock);
	sv_init(&log->l_flush_wait, 0, "flush_wait");

	xlog_trace_loggrant_alloc(log);
	/* log record size must be multiple of BBSIZE; see xlog_rec_header_t */
	ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);

@@ -1285,6 +1314,8 @@ xlog_alloc_log(xfs_mount_t *mp,
		sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force");
		sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write");

		xlog_trace_iclog_alloc(iclog);

		iclogp = &iclog->ic_next;
	}
	*iclogp = log->l_iclog;			/* complete ring */
@@ -1565,11 +1596,7 @@ xlog_dealloc_log(xlog_t *log)
		sv_destroy(&iclog->ic_force_wait);
		sv_destroy(&iclog->ic_write_wait);
		xfs_buf_free(iclog->ic_bp);
#ifdef XFS_LOG_TRACE
		if (iclog->ic_trace != NULL) {
			ktrace_free(iclog->ic_trace);
		}
#endif
		xlog_trace_iclog_dealloc(iclog);
		next_iclog = iclog->ic_next;
		kmem_free(iclog);
		iclog = next_iclog;
@@ -1578,14 +1605,7 @@ xlog_dealloc_log(xlog_t *log)
	spinlock_destroy(&log->l_grant_lock);

	xfs_buf_free(log->l_xbuf);
#ifdef XFS_LOG_TRACE
	if (log->l_trace != NULL) {
		ktrace_free(log->l_trace);
	}
	if (log->l_grant_trace != NULL) {
		ktrace_free(log->l_grant_trace);
	}
#endif
	xlog_trace_loggrant_dealloc(log);
	log->l_mp->m_log = NULL;
	kmem_free(log);
}	/* xlog_dealloc_log */
Loading