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

Commit 37cd9600 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-v3.6-rc1' of git://oss.sgi.com/xfs/xfs

Pull xfs update from Ben Myers:
 "Numerous cleanups and several bug fixes.  Here are some highlights:

   - Discontiguous directory buffer support
   - Inode allocator refactoring
   - Removal of the IO lock in inode reclaim
   - Implementation of .update_time
   - Fix for handling of EOF in xfs_vm_writepage
   - Fix for races in xfsaild, and idle mode is re-enabled
   - Fix for a crash in xfs_buf completion handlers on unmount."

Fix up trivial conflicts in fs/xfs/{xfs_buf.c,xfs_log.c,xfs_log_priv.h}
due to duplicate patches that had already been merged for 3.5.

* tag 'for-linus-v3.6-rc1' of git://oss.sgi.com/xfs/xfs: (44 commits)
  xfs: wait for the write the superblock on unmount
  xfs: re-enable xfsaild idle mode and fix associated races
  xfs: remove iolock lock classes
  xfs: avoid the iolock in xfs_free_eofblocks for evicted inodes
  xfs: do not take the iolock in xfs_inactive
  xfs: remove xfs_inactive_attrs
  xfs: clean up xfs_inactive
  xfs: do not read the AGI buffer in xfs_dialloc until nessecary
  xfs: refactor xfs_ialloc_ag_select
  xfs: add a short cut to xfs_dialloc for the non-NULL agbp case
  xfs: remove the alloc_done argument to xfs_dialloc
  xfs: split xfs_dialloc
  xfs: remove xfs_ialloc_find_free
  Prefix IO_XX flags with XFS_IO_XX to avoid namespace colision.
  xfs: remove xfs_inotobp
  xfs: merge xfs_itobp into xfs_imap_to_bp
  xfs: handle EOF correctly in xfs_vm_writepage
  xfs: implement ->update_time
  xfs: fix comment typo of struct xfs_da_blkinfo.
  xfs: do not call xfs_bdstrat_cb in xfs_buf_iodone_callbacks
  ...
parents 95b18e69 9a57fa8e
Loading
Loading
Loading
Loading
+0 −14
Original line number Original line Diff line number Diff line
@@ -50,20 +50,6 @@ typedef struct xfs_alloc_rec_incore {
/* btree pointer type */
/* btree pointer type */
typedef __be32 xfs_alloc_ptr_t;
typedef __be32 xfs_alloc_ptr_t;


/*
 * Minimum and maximum blocksize and sectorsize.
 * The blocksize upper limit is pretty much arbitrary.
 * The sectorsize upper limit is due to sizeof(sb_sectsize).
 */
#define XFS_MIN_BLOCKSIZE_LOG	9	/* i.e. 512 bytes */
#define XFS_MAX_BLOCKSIZE_LOG	16	/* i.e. 65536 bytes */
#define XFS_MIN_BLOCKSIZE	(1 << XFS_MIN_BLOCKSIZE_LOG)
#define XFS_MAX_BLOCKSIZE	(1 << XFS_MAX_BLOCKSIZE_LOG)
#define XFS_MIN_SECTORSIZE_LOG	9	/* i.e. 512 bytes */
#define XFS_MAX_SECTORSIZE_LOG	15	/* i.e. 32768 bytes */
#define XFS_MIN_SECTORSIZE	(1 << XFS_MIN_SECTORSIZE_LOG)
#define XFS_MAX_SECTORSIZE	(1 << XFS_MAX_SECTORSIZE_LOG)

/*
/*
 * Block numbers in the AG:
 * Block numbers in the AG:
 * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
 * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
+47 −32
Original line number Original line Diff line number Diff line
@@ -179,7 +179,7 @@ xfs_finish_ioend(
	if (atomic_dec_and_test(&ioend->io_remaining)) {
	if (atomic_dec_and_test(&ioend->io_remaining)) {
		struct xfs_mount	*mp = XFS_I(ioend->io_inode)->i_mount;
		struct xfs_mount	*mp = XFS_I(ioend->io_inode)->i_mount;


		if (ioend->io_type == IO_UNWRITTEN)
		if (ioend->io_type == XFS_IO_UNWRITTEN)
			queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
			queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
		else if (ioend->io_append_trans)
		else if (ioend->io_append_trans)
			queue_work(mp->m_data_workqueue, &ioend->io_work);
			queue_work(mp->m_data_workqueue, &ioend->io_work);
@@ -210,7 +210,7 @@ xfs_end_io(
	 * For unwritten extents we need to issue transactions to convert a
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 * range to normal written extens after the data I/O has finished.
	 */
	 */
	if (ioend->io_type == IO_UNWRITTEN) {
	if (ioend->io_type == XFS_IO_UNWRITTEN) {
		/*
		/*
		 * For buffered I/O we never preallocate a transaction when
		 * For buffered I/O we never preallocate a transaction when
		 * doing the unwritten extent conversion, but for direct I/O
		 * doing the unwritten extent conversion, but for direct I/O
@@ -312,7 +312,7 @@ xfs_map_blocks(
	if (XFS_FORCED_SHUTDOWN(mp))
	if (XFS_FORCED_SHUTDOWN(mp))
		return -XFS_ERROR(EIO);
		return -XFS_ERROR(EIO);


	if (type == IO_UNWRITTEN)
	if (type == XFS_IO_UNWRITTEN)
		bmapi_flags |= XFS_BMAPI_IGSTATE;
		bmapi_flags |= XFS_BMAPI_IGSTATE;


	if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
	if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
@@ -323,10 +323,10 @@ xfs_map_blocks(


	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
	       (ip->i_df.if_flags & XFS_IFEXTENTS));
	       (ip->i_df.if_flags & XFS_IFEXTENTS));
	ASSERT(offset <= mp->m_maxioffset);
	ASSERT(offset <= mp->m_super->s_maxbytes);


	if (offset + count > mp->m_maxioffset)
	if (offset + count > mp->m_super->s_maxbytes)
		count = mp->m_maxioffset - offset;
		count = mp->m_super->s_maxbytes - offset;
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);
	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
@@ -336,7 +336,7 @@ xfs_map_blocks(
	if (error)
	if (error)
		return -XFS_ERROR(error);
		return -XFS_ERROR(error);


	if (type == IO_DELALLOC &&
	if (type == XFS_IO_DELALLOC &&
	    (!nimaps || isnullstartblock(imap->br_startblock))) {
	    (!nimaps || isnullstartblock(imap->br_startblock))) {
		error = xfs_iomap_write_allocate(ip, offset, count, imap);
		error = xfs_iomap_write_allocate(ip, offset, count, imap);
		if (!error)
		if (!error)
@@ -345,7 +345,7 @@ xfs_map_blocks(
	}
	}


#ifdef DEBUG
#ifdef DEBUG
	if (type == IO_UNWRITTEN) {
	if (type == XFS_IO_UNWRITTEN) {
		ASSERT(nimaps);
		ASSERT(nimaps);
		ASSERT(imap->br_startblock != HOLESTARTBLOCK);
		ASSERT(imap->br_startblock != HOLESTARTBLOCK);
		ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
		ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
@@ -634,11 +634,11 @@ xfs_check_page_type(
		bh = head = page_buffers(page);
		bh = head = page_buffers(page);
		do {
		do {
			if (buffer_unwritten(bh))
			if (buffer_unwritten(bh))
				acceptable += (type == IO_UNWRITTEN);
				acceptable += (type == XFS_IO_UNWRITTEN);
			else if (buffer_delay(bh))
			else if (buffer_delay(bh))
				acceptable += (type == IO_DELALLOC);
				acceptable += (type == XFS_IO_DELALLOC);
			else if (buffer_dirty(bh) && buffer_mapped(bh))
			else if (buffer_dirty(bh) && buffer_mapped(bh))
				acceptable += (type == IO_OVERWRITE);
				acceptable += (type == XFS_IO_OVERWRITE);
			else
			else
				break;
				break;
		} while ((bh = bh->b_this_page) != head);
		} while ((bh = bh->b_this_page) != head);
@@ -721,11 +721,11 @@ xfs_convert_page(
		if (buffer_unwritten(bh) || buffer_delay(bh) ||
		if (buffer_unwritten(bh) || buffer_delay(bh) ||
		    buffer_mapped(bh)) {
		    buffer_mapped(bh)) {
			if (buffer_unwritten(bh))
			if (buffer_unwritten(bh))
				type = IO_UNWRITTEN;
				type = XFS_IO_UNWRITTEN;
			else if (buffer_delay(bh))
			else if (buffer_delay(bh))
				type = IO_DELALLOC;
				type = XFS_IO_DELALLOC;
			else
			else
				type = IO_OVERWRITE;
				type = XFS_IO_OVERWRITE;


			if (!xfs_imap_valid(inode, imap, offset)) {
			if (!xfs_imap_valid(inode, imap, offset)) {
				done = 1;
				done = 1;
@@ -733,7 +733,7 @@ xfs_convert_page(
			}
			}


			lock_buffer(bh);
			lock_buffer(bh);
			if (type != IO_OVERWRITE)
			if (type != XFS_IO_OVERWRITE)
				xfs_map_at_offset(inode, bh, imap, offset);
				xfs_map_at_offset(inode, bh, imap, offset);
			xfs_add_to_ioend(inode, bh, offset, type,
			xfs_add_to_ioend(inode, bh, offset, type,
					 ioendp, done);
					 ioendp, done);
@@ -831,7 +831,7 @@ xfs_aops_discard_page(
	struct buffer_head	*bh, *head;
	struct buffer_head	*bh, *head;
	loff_t			offset = page_offset(page);
	loff_t			offset = page_offset(page);


	if (!xfs_check_page_type(page, IO_DELALLOC))
	if (!xfs_check_page_type(page, XFS_IO_DELALLOC))
		goto out_invalidate;
		goto out_invalidate;


	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -927,11 +927,26 @@ xfs_vm_writepage(
	end_index = offset >> PAGE_CACHE_SHIFT;
	end_index = offset >> PAGE_CACHE_SHIFT;
	last_index = (offset - 1) >> PAGE_CACHE_SHIFT;
	last_index = (offset - 1) >> PAGE_CACHE_SHIFT;
	if (page->index >= end_index) {
	if (page->index >= end_index) {
		if ((page->index >= end_index + 1) ||
		unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1);
		    !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) {

		/*
		 * Just skip the page if it is fully outside i_size, e.g. due
		 * to a truncate operation that is in progress.
		 */
		if (page->index >= end_index + 1 || offset_into_page == 0) {
			unlock_page(page);
			unlock_page(page);
			return 0;
			return 0;
		}
		}

		/*
		 * The page straddles i_size.  It must be zeroed out on each
		 * and every writepage invocation because it may be mmapped.
		 * "A file is mapped in multiples of the page size.  For a file
		 * that is not a multiple of the  page size, the remaining
		 * memory is zeroed when mapped, and writes to that region are
		 * not written out to the file."
		 */
		zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE);
	}
	}


	end_offset = min_t(unsigned long long,
	end_offset = min_t(unsigned long long,
@@ -941,7 +956,7 @@ xfs_vm_writepage(


	bh = head = page_buffers(page);
	bh = head = page_buffers(page);
	offset = page_offset(page);
	offset = page_offset(page);
	type = IO_OVERWRITE;
	type = XFS_IO_OVERWRITE;


	if (wbc->sync_mode == WB_SYNC_NONE)
	if (wbc->sync_mode == WB_SYNC_NONE)
		nonblocking = 1;
		nonblocking = 1;
@@ -966,18 +981,18 @@ xfs_vm_writepage(
		}
		}


		if (buffer_unwritten(bh)) {
		if (buffer_unwritten(bh)) {
			if (type != IO_UNWRITTEN) {
			if (type != XFS_IO_UNWRITTEN) {
				type = IO_UNWRITTEN;
				type = XFS_IO_UNWRITTEN;
				imap_valid = 0;
				imap_valid = 0;
			}
			}
		} else if (buffer_delay(bh)) {
		} else if (buffer_delay(bh)) {
			if (type != IO_DELALLOC) {
			if (type != XFS_IO_DELALLOC) {
				type = IO_DELALLOC;
				type = XFS_IO_DELALLOC;
				imap_valid = 0;
				imap_valid = 0;
			}
			}
		} else if (buffer_uptodate(bh)) {
		} else if (buffer_uptodate(bh)) {
			if (type != IO_OVERWRITE) {
			if (type != XFS_IO_OVERWRITE) {
				type = IO_OVERWRITE;
				type = XFS_IO_OVERWRITE;
				imap_valid = 0;
				imap_valid = 0;
			}
			}
		} else {
		} else {
@@ -1013,7 +1028,7 @@ xfs_vm_writepage(
		}
		}
		if (imap_valid) {
		if (imap_valid) {
			lock_buffer(bh);
			lock_buffer(bh);
			if (type != IO_OVERWRITE)
			if (type != XFS_IO_OVERWRITE)
				xfs_map_at_offset(inode, bh, &imap, offset);
				xfs_map_at_offset(inode, bh, &imap, offset);
			xfs_add_to_ioend(inode, bh, offset, type, &ioend,
			xfs_add_to_ioend(inode, bh, offset, type, &ioend,
					 new_ioend);
					 new_ioend);
@@ -1054,7 +1069,7 @@ xfs_vm_writepage(
		 * Reserve log space if we might write beyond the on-disk
		 * Reserve log space if we might write beyond the on-disk
		 * inode size.
		 * inode size.
		 */
		 */
		if (ioend->io_type != IO_UNWRITTEN &&
		if (ioend->io_type != XFS_IO_UNWRITTEN &&
		    xfs_ioend_is_append(ioend)) {
		    xfs_ioend_is_append(ioend)) {
			err = xfs_setfilesize_trans_alloc(ioend);
			err = xfs_setfilesize_trans_alloc(ioend);
			if (err)
			if (err)
@@ -1162,9 +1177,9 @@ __xfs_get_blocks(
		lockmode = xfs_ilock_map_shared(ip);
		lockmode = xfs_ilock_map_shared(ip);
	}
	}


	ASSERT(offset <= mp->m_maxioffset);
	ASSERT(offset <= mp->m_super->s_maxbytes);
	if (offset + size > mp->m_maxioffset)
	if (offset + size > mp->m_super->s_maxbytes)
		size = mp->m_maxioffset - offset;
		size = mp->m_super->s_maxbytes - offset;
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);


@@ -1351,7 +1366,7 @@ xfs_end_io_direct_write(
	ioend->io_iocb = iocb;
	ioend->io_iocb = iocb;
	ioend->io_result = ret;
	ioend->io_result = ret;
	if (private && size > 0)
	if (private && size > 0)
		ioend->io_type = IO_UNWRITTEN;
		ioend->io_type = XFS_IO_UNWRITTEN;


	if (is_async) {
	if (is_async) {
		ioend->io_isasync = 1;
		ioend->io_isasync = 1;
@@ -1383,7 +1398,7 @@ xfs_vm_direct_IO(
		 * and converts at least on unwritten extent we will cancel
		 * and converts at least on unwritten extent we will cancel
		 * the still clean transaction after the I/O has finished.
		 * the still clean transaction after the I/O has finished.
		 */
		 */
		iocb->private = ioend = xfs_alloc_ioend(inode, IO_DIRECT);
		iocb->private = ioend = xfs_alloc_ioend(inode, XFS_IO_DIRECT);
		if (offset + size > XFS_I(inode)->i_d.di_size) {
		if (offset + size > XFS_I(inode)->i_d.di_size) {
			ret = xfs_setfilesize_trans_alloc(ioend);
			ret = xfs_setfilesize_trans_alloc(ioend);
			if (ret)
			if (ret)
+7 −7
Original line number Original line Diff line number Diff line
@@ -24,17 +24,17 @@ extern mempool_t *xfs_ioend_pool;
 * Types of I/O for bmap clustering and I/O completion tracking.
 * Types of I/O for bmap clustering and I/O completion tracking.
 */
 */
enum {
enum {
	IO_DIRECT = 0,	/* special case for direct I/O ioends */
	XFS_IO_DIRECT = 0,	/* special case for direct I/O ioends */
	IO_DELALLOC,	/* mapping covers delalloc region */
	XFS_IO_DELALLOC,	/* covers delalloc region */
	IO_UNWRITTEN,	/* mapping covers allocated but uninitialized data */
	XFS_IO_UNWRITTEN,	/* covers allocated but uninitialized data */
	IO_OVERWRITE,	/* mapping covers already allocated extent */
	XFS_IO_OVERWRITE,	/* covers already allocated extent */
};
};


#define XFS_IO_TYPES \
#define XFS_IO_TYPES \
	{ 0,			"" }, \
	{ 0,			"" }, \
	{ IO_DELALLOC,		"delalloc" }, \
	{ XFS_IO_DELALLOC,		"delalloc" }, \
	{ IO_UNWRITTEN,		"unwritten" }, \
	{ XFS_IO_UNWRITTEN,		"unwritten" }, \
	{ IO_OVERWRITE,		"overwrite" }
	{ XFS_IO_OVERWRITE,		"overwrite" }


/*
/*
 * xfs_ioend struct manages large extent writes for XFS.
 * xfs_ioend struct manages large extent writes for XFS.
+36 −42
Original line number Original line Diff line number Diff line
@@ -893,7 +893,7 @@ STATIC int
xfs_attr_leaf_addname(xfs_da_args_t *args)
xfs_attr_leaf_addname(xfs_da_args_t *args)
{
{
	xfs_inode_t *dp;
	xfs_inode_t *dp;
	xfs_dabuf_t *bp;
	struct xfs_buf *bp;
	int retval, error, committed, forkoff;
	int retval, error, committed, forkoff;


	trace_xfs_attr_leaf_addname(args);
	trace_xfs_attr_leaf_addname(args);
@@ -915,11 +915,11 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
	 */
	 */
	retval = xfs_attr_leaf_lookup_int(bp, args);
	retval = xfs_attr_leaf_lookup_int(bp, args);
	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
		xfs_da_brelse(args->trans, bp);
		xfs_trans_brelse(args->trans, bp);
		return(retval);
		return(retval);
	} else if (retval == EEXIST) {
	} else if (retval == EEXIST) {
		if (args->flags & ATTR_CREATE) {	/* pure create op */
		if (args->flags & ATTR_CREATE) {	/* pure create op */
			xfs_da_brelse(args->trans, bp);
			xfs_trans_brelse(args->trans, bp);
			return(retval);
			return(retval);
		}
		}


@@ -937,7 +937,6 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
	 * if required.
	 * if required.
	 */
	 */
	retval = xfs_attr_leaf_add(bp, args);
	retval = xfs_attr_leaf_add(bp, args);
	xfs_da_buf_done(bp);
	if (retval == ENOSPC) {
	if (retval == ENOSPC) {
		/*
		/*
		 * Promote the attribute list to the Btree format, then
		 * Promote the attribute list to the Btree format, then
@@ -1065,8 +1064,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
			 */
			 */
			if (committed)
			if (committed)
				xfs_trans_ijoin(args->trans, dp, 0);
				xfs_trans_ijoin(args->trans, dp, 0);
		} else
		}
			xfs_da_buf_done(bp);


		/*
		/*
		 * Commit the remove and start the next trans in series.
		 * Commit the remove and start the next trans in series.
@@ -1092,7 +1090,7 @@ STATIC int
xfs_attr_leaf_removename(xfs_da_args_t *args)
xfs_attr_leaf_removename(xfs_da_args_t *args)
{
{
	xfs_inode_t *dp;
	xfs_inode_t *dp;
	xfs_dabuf_t *bp;
	struct xfs_buf *bp;
	int error, committed, forkoff;
	int error, committed, forkoff;


	trace_xfs_attr_leaf_removename(args);
	trace_xfs_attr_leaf_removename(args);
@@ -1111,7 +1109,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
	ASSERT(bp != NULL);
	ASSERT(bp != NULL);
	error = xfs_attr_leaf_lookup_int(bp, args);
	error = xfs_attr_leaf_lookup_int(bp, args);
	if (error == ENOATTR) {
	if (error == ENOATTR) {
		xfs_da_brelse(args->trans, bp);
		xfs_trans_brelse(args->trans, bp);
		return(error);
		return(error);
	}
	}


@@ -1141,8 +1139,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
		 */
		 */
		if (committed)
		if (committed)
			xfs_trans_ijoin(args->trans, dp, 0);
			xfs_trans_ijoin(args->trans, dp, 0);
	} else
	}
		xfs_da_buf_done(bp);
	return(0);
	return(0);
}
}


@@ -1155,7 +1152,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
STATIC int
STATIC int
xfs_attr_leaf_get(xfs_da_args_t *args)
xfs_attr_leaf_get(xfs_da_args_t *args)
{
{
	xfs_dabuf_t *bp;
	struct xfs_buf *bp;
	int error;
	int error;


	args->blkno = 0;
	args->blkno = 0;
@@ -1167,11 +1164,11 @@ xfs_attr_leaf_get(xfs_da_args_t *args)


	error = xfs_attr_leaf_lookup_int(bp, args);
	error = xfs_attr_leaf_lookup_int(bp, args);
	if (error != EEXIST)  {
	if (error != EEXIST)  {
		xfs_da_brelse(args->trans, bp);
		xfs_trans_brelse(args->trans, bp);
		return(error);
		return(error);
	}
	}
	error = xfs_attr_leaf_getvalue(bp, args);
	error = xfs_attr_leaf_getvalue(bp, args);
	xfs_da_brelse(args->trans, bp);
	xfs_trans_brelse(args->trans, bp);
	if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
	if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
		error = xfs_attr_rmtval_get(args);
		error = xfs_attr_rmtval_get(args);
	}
	}
@@ -1186,23 +1183,23 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
{
{
	xfs_attr_leafblock_t *leaf;
	xfs_attr_leafblock_t *leaf;
	int error;
	int error;
	xfs_dabuf_t *bp;
	struct xfs_buf *bp;


	context->cursor->blkno = 0;
	context->cursor->blkno = 0;
	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
	if (error)
	if (error)
		return XFS_ERROR(error);
		return XFS_ERROR(error);
	ASSERT(bp != NULL);
	ASSERT(bp != NULL);
	leaf = bp->data;
	leaf = bp->b_addr;
	if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
	if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
				     context->dp->i_mount, leaf);
				     context->dp->i_mount, leaf);
		xfs_da_brelse(NULL, bp);
		xfs_trans_brelse(NULL, bp);
		return XFS_ERROR(EFSCORRUPTED);
		return XFS_ERROR(EFSCORRUPTED);
	}
	}


	error = xfs_attr_leaf_list_int(bp, context);
	error = xfs_attr_leaf_list_int(bp, context);
	xfs_da_brelse(NULL, bp);
	xfs_trans_brelse(NULL, bp);
	return XFS_ERROR(error);
	return XFS_ERROR(error);
}
}


@@ -1489,7 +1486,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
	xfs_da_state_t *state;
	xfs_da_state_t *state;
	xfs_da_state_blk_t *blk;
	xfs_da_state_blk_t *blk;
	xfs_inode_t *dp;
	xfs_inode_t *dp;
	xfs_dabuf_t *bp;
	struct xfs_buf *bp;
	int retval, error, committed, forkoff;
	int retval, error, committed, forkoff;


	trace_xfs_attr_node_removename(args);
	trace_xfs_attr_node_removename(args);
@@ -1601,14 +1598,13 @@ xfs_attr_node_removename(xfs_da_args_t *args)
		 */
		 */
		ASSERT(state->path.active == 1);
		ASSERT(state->path.active == 1);
		ASSERT(state->path.blk[0].bp);
		ASSERT(state->path.blk[0].bp);
		xfs_da_buf_done(state->path.blk[0].bp);
		state->path.blk[0].bp = NULL;
		state->path.blk[0].bp = NULL;


		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
						     XFS_ATTR_FORK);
						     XFS_ATTR_FORK);
		if (error)
		if (error)
			goto out;
			goto out;
		ASSERT((((xfs_attr_leafblock_t *)bp->data)->hdr.info.magic) ==
		ASSERT((((xfs_attr_leafblock_t *)bp->b_addr)->hdr.info.magic) ==
		       cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
		       cpu_to_be16(XFS_ATTR_LEAF_MAGIC));


		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
@@ -1635,7 +1631,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
			if (committed)
			if (committed)
				xfs_trans_ijoin(args->trans, dp, 0);
				xfs_trans_ijoin(args->trans, dp, 0);
		} else
		} else
			xfs_da_brelse(args->trans, bp);
			xfs_trans_brelse(args->trans, bp);
	}
	}
	error = 0;
	error = 0;


@@ -1665,8 +1661,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
		if (blk->bp) {
		if (blk->bp) {
			blk->disk_blkno = xfs_da_blkno(blk->bp);
			blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
			xfs_da_buf_done(blk->bp);
			blk->bp = NULL;
			blk->bp = NULL;
		} else {
		} else {
			blk->disk_blkno = 0;
			blk->disk_blkno = 0;
@@ -1681,8 +1676,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
		if (blk->bp) {
		if (blk->bp) {
			blk->disk_blkno = xfs_da_blkno(blk->bp);
			blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
			xfs_da_buf_done(blk->bp);
			blk->bp = NULL;
			blk->bp = NULL;
		} else {
		} else {
			blk->disk_blkno = 0;
			blk->disk_blkno = 0;
@@ -1792,7 +1786,7 @@ xfs_attr_node_get(xfs_da_args_t *args)
	 * If not in a transaction, we have to release all the buffers.
	 * If not in a transaction, we have to release all the buffers.
	 */
	 */
	for (i = 0; i < state->path.active; i++) {
	for (i = 0; i < state->path.active; i++) {
		xfs_da_brelse(args->trans, state->path.blk[i].bp);
		xfs_trans_brelse(args->trans, state->path.blk[i].bp);
		state->path.blk[i].bp = NULL;
		state->path.blk[i].bp = NULL;
	}
	}


@@ -1808,7 +1802,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
	xfs_da_intnode_t *node;
	xfs_da_intnode_t *node;
	xfs_da_node_entry_t *btree;
	xfs_da_node_entry_t *btree;
	int error, i;
	int error, i;
	xfs_dabuf_t *bp;
	struct xfs_buf *bp;


	cursor = context->cursor;
	cursor = context->cursor;
	cursor->initted = 1;
	cursor->initted = 1;
@@ -1825,30 +1819,30 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
		if ((error != 0) && (error != EFSCORRUPTED))
		if ((error != 0) && (error != EFSCORRUPTED))
			return(error);
			return(error);
		if (bp) {
		if (bp) {
			node = bp->data;
			node = bp->b_addr;
			switch (be16_to_cpu(node->hdr.info.magic)) {
			switch (be16_to_cpu(node->hdr.info.magic)) {
			case XFS_DA_NODE_MAGIC:
			case XFS_DA_NODE_MAGIC:
				trace_xfs_attr_list_wrong_blk(context);
				trace_xfs_attr_list_wrong_blk(context);
				xfs_da_brelse(NULL, bp);
				xfs_trans_brelse(NULL, bp);
				bp = NULL;
				bp = NULL;
				break;
				break;
			case XFS_ATTR_LEAF_MAGIC:
			case XFS_ATTR_LEAF_MAGIC:
				leaf = bp->data;
				leaf = bp->b_addr;
				if (cursor->hashval > be32_to_cpu(leaf->entries[
				if (cursor->hashval > be32_to_cpu(leaf->entries[
				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {
				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {
					trace_xfs_attr_list_wrong_blk(context);
					trace_xfs_attr_list_wrong_blk(context);
					xfs_da_brelse(NULL, bp);
					xfs_trans_brelse(NULL, bp);
					bp = NULL;
					bp = NULL;
				} else if (cursor->hashval <=
				} else if (cursor->hashval <=
					     be32_to_cpu(leaf->entries[0].hashval)) {
					     be32_to_cpu(leaf->entries[0].hashval)) {
					trace_xfs_attr_list_wrong_blk(context);
					trace_xfs_attr_list_wrong_blk(context);
					xfs_da_brelse(NULL, bp);
					xfs_trans_brelse(NULL, bp);
					bp = NULL;
					bp = NULL;
				}
				}
				break;
				break;
			default:
			default:
				trace_xfs_attr_list_wrong_blk(context);
				trace_xfs_attr_list_wrong_blk(context);
				xfs_da_brelse(NULL, bp);
				xfs_trans_brelse(NULL, bp);
				bp = NULL;
				bp = NULL;
			}
			}
		}
		}
@@ -1873,7 +1867,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
						 context->dp->i_mount);
						 context->dp->i_mount);
				return(XFS_ERROR(EFSCORRUPTED));
				return(XFS_ERROR(EFSCORRUPTED));
			}
			}
			node = bp->data;
			node = bp->b_addr;
			if (node->hdr.info.magic ==
			if (node->hdr.info.magic ==
			    cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
			    cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
				break;
				break;
@@ -1883,7 +1877,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
						     XFS_ERRLEVEL_LOW,
						     XFS_ERRLEVEL_LOW,
						     context->dp->i_mount,
						     context->dp->i_mount,
						     node);
						     node);
				xfs_da_brelse(NULL, bp);
				xfs_trans_brelse(NULL, bp);
				return(XFS_ERROR(EFSCORRUPTED));
				return(XFS_ERROR(EFSCORRUPTED));
			}
			}
			btree = node->btree;
			btree = node->btree;
@@ -1898,10 +1892,10 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
				}
				}
			}
			}
			if (i == be16_to_cpu(node->hdr.count)) {
			if (i == be16_to_cpu(node->hdr.count)) {
				xfs_da_brelse(NULL, bp);
				xfs_trans_brelse(NULL, bp);
				return(0);
				return(0);
			}
			}
			xfs_da_brelse(NULL, bp);
			xfs_trans_brelse(NULL, bp);
		}
		}
	}
	}
	ASSERT(bp != NULL);
	ASSERT(bp != NULL);
@@ -1912,24 +1906,24 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
	 * adding the information.
	 * adding the information.
	 */
	 */
	for (;;) {
	for (;;) {
		leaf = bp->data;
		leaf = bp->b_addr;
		if (unlikely(leaf->hdr.info.magic !=
		if (unlikely(leaf->hdr.info.magic !=
			     cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
			     cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
					     XFS_ERRLEVEL_LOW,
					     XFS_ERRLEVEL_LOW,
					     context->dp->i_mount, leaf);
					     context->dp->i_mount, leaf);
			xfs_da_brelse(NULL, bp);
			xfs_trans_brelse(NULL, bp);
			return(XFS_ERROR(EFSCORRUPTED));
			return(XFS_ERROR(EFSCORRUPTED));
		}
		}
		error = xfs_attr_leaf_list_int(bp, context);
		error = xfs_attr_leaf_list_int(bp, context);
		if (error) {
		if (error) {
			xfs_da_brelse(NULL, bp);
			xfs_trans_brelse(NULL, bp);
			return error;
			return error;
		}
		}
		if (context->seen_enough || leaf->hdr.info.forw == 0)
		if (context->seen_enough || leaf->hdr.info.forw == 0)
			break;
			break;
		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
		xfs_da_brelse(NULL, bp);
		xfs_trans_brelse(NULL, bp);
		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
					      &bp, XFS_ATTR_FORK);
					      &bp, XFS_ATTR_FORK);
		if (error)
		if (error)
@@ -1941,7 +1935,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
			return(XFS_ERROR(EFSCORRUPTED));
			return(XFS_ERROR(EFSCORRUPTED));
		}
		}
	}
	}
	xfs_da_brelse(NULL, bp);
	xfs_trans_brelse(NULL, bp);
	return(0);
	return(0);
}
}


+138 −117

File changed.

Preview size limit exceeded, changes collapsed.

Loading