Commit b477ff98 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xfs-merge-6.14' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull XFS updates from Carlos Maiolino:
 "This is mostly focused on the implementation of reflink and
  reverse-mapping support for XFS's real-time devices.

  It also includes several bugfixes.

   - Implement reflink support for the realtime device

   - Implement reverse-mapping support for the realtime device

   - Several bug fixes and cleanups"

* tag 'xfs-merge-6.14' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (121 commits)
  xfs: fix buffer lookup vs release race
  xfs: check for dead buffers in xfs_buf_find_insert
  xfs: add a b_iodone callback to struct xfs_buf
  xfs: move b_li_list based retry handling to common code
  xfs: simplify xfsaild_resubmit_item
  xfs: always complete the buffer inline in xfs_buf_submit
  xfs: remove the extra buffer reference in xfs_buf_submit
  xfs: move invalidate_kernel_vmap_range to xfs_buf_ioend
  xfs: simplify buffer I/O submission
  xfs: move in-memory buftarg handling out of _xfs_buf_ioapply
  xfs: move write verification out of _xfs_buf_ioapply
  xfs: remove xfs_buf_delwri_submit_buffers
  xfs: simplify xfs_buf_delwri_pushbuf
  xfs: move xfs_buf_iowait out of (__)xfs_buf_submit
  xfs: remove the incorrect comment about the b_pag field
  xfs: remove the incorrect comment above xfs_buf_free_maps
  xfs: fix a double completion for buffers on in-memory targets
  xfs/libxfs: replace kmalloc() and memcpy() with kmemdup()
  xfs: constify feature checks
  xfs: refactor xfs_fs_statfs
  ...
parents d0d106a2 ee10f6fc
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ xfs-y += $(addprefix libxfs/, \
				   xfs_rmap_btree.o \
				   xfs_refcount.o \
				   xfs_refcount_btree.o \
				   xfs_rtrefcount_btree.o \
				   xfs_rtrmap_btree.o \
				   xfs_sb.o \
				   xfs_symlink_remote.o \
				   xfs_trans_inode.o \
@@ -193,6 +195,8 @@ xfs-$(CONFIG_XFS_ONLINE_SCRUB_STATS) += scrub/stats.o
xfs-$(CONFIG_XFS_RT)		+= $(addprefix scrub/, \
				   rgsuper.o \
				   rtbitmap.o \
				   rtrefcount.o \
				   rtrmap.o \
				   rtsummary.o \
				   )

@@ -232,6 +236,8 @@ xfs-y += $(addprefix scrub/, \

xfs-$(CONFIG_XFS_RT)		+= $(addprefix scrub/, \
				   rtbitmap_repair.o \
				   rtrefcount_repair.o \
				   rtrmap_repair.o \
				   rtsummary_repair.o \
				   )

+3 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ xfs_ag_resv_needed(
	case XFS_AG_RESV_RMAPBT:
		len -= xfs_perag_resv(pag, type)->ar_reserved;
		break;
	case XFS_AG_RESV_METAFILE:
	case XFS_AG_RESV_NONE:
		/* empty */
		break;
@@ -347,6 +348,7 @@ xfs_ag_resv_alloc_extent(

	switch (type) {
	case XFS_AG_RESV_AGFL:
	case XFS_AG_RESV_METAFILE:
		return;
	case XFS_AG_RESV_METADATA:
	case XFS_AG_RESV_RMAPBT:
@@ -389,6 +391,7 @@ xfs_ag_resv_free_extent(

	switch (type) {
	case XFS_AG_RESV_AGFL:
	case XFS_AG_RESV_METAFILE:
		return;
	case XFS_AG_RESV_METADATA:
	case XFS_AG_RESV_RMAPBT:
+1 −3
Original line number Diff line number Diff line
@@ -1004,9 +1004,7 @@ xfs_attr_add_fork(
	unsigned int		blks;		/* space reservation */
	int			error;		/* error return value */

	if (xfs_is_metadir_inode(ip))
		ASSERT(XFS_IS_DQDETACHED(ip));
	else
	if (!xfs_is_metadir_inode(ip))
		ASSERT(!XFS_NOT_DQATTACHED(mp, ip));

	blks = XFS_ADDAFORK_SPACE_RES(mp);
+19 −15
Original line number Diff line number Diff line
@@ -615,7 +615,7 @@ xfs_bmap_btree_to_extents(
	xfs_trans_binval(tp, cbp);
	if (cur->bc_levels[0].bp == cbp)
		cur->bc_levels[0].bp = NULL;
	xfs_iroot_realloc(ip, -1, whichfork);
	xfs_bmap_broot_realloc(ip, whichfork, 0);
	ASSERT(ifp->if_broot == NULL);
	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
	*logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
@@ -659,12 +659,11 @@ xfs_bmap_extents_to_btree(
	 * Make space in the inode incore. This needs to be undone if we fail
	 * to expand the root.
	 */
	xfs_iroot_realloc(ip, 1, whichfork);
	block = xfs_bmap_broot_realloc(ip, whichfork, 1);

	/*
	 * Fill in the root.
	 */
	block = ifp->if_broot;
	xfs_bmbt_init_block(ip, block, NULL, 1, 1);
	/*
	 * Need a cursor.  Can't allocate until bb_level is filled in.
@@ -746,7 +745,7 @@ xfs_bmap_extents_to_btree(
out_unreserve_dquot:
	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
out_root_realloc:
	xfs_iroot_realloc(ip, -1, whichfork);
	xfs_bmap_broot_realloc(ip, whichfork, 0);
	ifp->if_format = XFS_DINODE_FMT_EXTENTS;
	ASSERT(ifp->if_broot == NULL);
	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
@@ -1043,9 +1042,7 @@ xfs_bmap_add_attrfork(
	int			error;		/* error return value */

	xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
	if (xfs_is_metadir_inode(ip))
		ASSERT(XFS_IS_DQDETACHED(ip));
	else
	if (!xfs_is_metadir_inode(ip))
		ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
	ASSERT(!xfs_inode_has_attr_fork(ip));

@@ -4567,8 +4564,9 @@ xfs_bmapi_write(
			 * the refcount btree for orphan recovery.
			 */
			if (whichfork == XFS_COW_FORK)
				xfs_refcount_alloc_cow_extent(tp, bma.blkno,
						bma.length);
				xfs_refcount_alloc_cow_extent(tp,
						XFS_IS_REALTIME_INODE(ip),
						bma.blkno, bma.length);
		}

		/* Deal with the allocated space we found.  */
@@ -4743,7 +4741,8 @@ xfs_bmapi_convert_one_delalloc(
		*seq = READ_ONCE(ifp->if_seq);

	if (whichfork == XFS_COW_FORK)
		xfs_refcount_alloc_cow_extent(tp, bma.blkno, bma.length);
		xfs_refcount_alloc_cow_extent(tp, XFS_IS_REALTIME_INODE(ip),
				bma.blkno, bma.length);

	error = xfs_bmap_btree_to_extents(tp, ip, bma.cur, &bma.logflags,
			whichfork);
@@ -5391,7 +5390,7 @@ xfs_bmap_del_extent_real(
		bool	isrt = xfs_ifork_is_realtime(ip, whichfork);

		if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) {
			xfs_refcount_decrease_extent(tp, del);
			xfs_refcount_decrease_extent(tp, isrt, del);
		} else if (isrt && !xfs_has_rtgroups(mp)) {
			error = xfs_bmap_free_rtblocks(tp, del);
		} else {
@@ -6501,9 +6500,8 @@ xfs_get_extsz_hint(
	 * No point in aligning allocations if we need to COW to actually
	 * write to them.
	 */
	if (xfs_is_always_cow_inode(ip))
		return 0;
	if ((ip->i_diflags & XFS_DIFLAG_EXTSIZE) && ip->i_extsize)
	if (!xfs_is_always_cow_inode(ip) &&
	    (ip->i_diflags & XFS_DIFLAG_EXTSIZE) && ip->i_extsize)
		return ip->i_extsize;
	if (XFS_IS_REALTIME_INODE(ip) &&
	    ip->i_mount->m_sb.sb_rextsize > 1)
@@ -6526,7 +6524,13 @@ xfs_get_cowextsz_hint(
	a = 0;
	if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
		a = ip->i_cowextsize;
	if (XFS_IS_REALTIME_INODE(ip)) {
		b = 0;
		if (ip->i_diflags & XFS_DIFLAG_EXTSIZE)
			b = ip->i_extsize;
	} else {
		b = xfs_get_extsz_hint(ip);
	}

	a = max(a, b);
	if (a == 0)
+111 −0
Original line number Diff line number Diff line
@@ -516,6 +516,116 @@ xfs_bmbt_keys_contiguous(
				 be64_to_cpu(key2->bmbt.br_startoff));
}

static inline void
xfs_bmbt_move_ptrs(
	struct xfs_mount	*mp,
	struct xfs_btree_block	*broot,
	short			old_size,
	size_t			new_size,
	unsigned int		numrecs)
{
	void			*dptr;
	void			*sptr;

	sptr = xfs_bmap_broot_ptr_addr(mp, broot, 1, old_size);
	dptr = xfs_bmap_broot_ptr_addr(mp, broot, 1, new_size);
	memmove(dptr, sptr, numrecs * sizeof(xfs_bmbt_ptr_t));
}

/*
 * Reallocate the space for if_broot based on the number of records.  Move the
 * records and pointers in if_broot to fit the new size.  When shrinking this
 * will eliminate holes between the records and pointers created by the caller.
 * When growing this will create holes to be filled in by the caller.
 *
 * The caller must not request to add more records than would fit in the
 * on-disk inode root.  If the if_broot is currently NULL, then if we are
 * adding records, one will be allocated.  The caller must also not request
 * that the number of records go below zero, although it can go to zero.
 *
 * ip -- the inode whose if_broot area is changing
 * whichfork -- which inode fork to change
 * new_numrecs -- the new number of records requested for the if_broot array
 *
 * Returns the incore btree root block.
 */
struct xfs_btree_block *
xfs_bmap_broot_realloc(
	struct xfs_inode	*ip,
	int			whichfork,
	unsigned int		new_numrecs)
{
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_ifork	*ifp = xfs_ifork_ptr(ip, whichfork);
	struct xfs_btree_block	*broot;
	unsigned int		new_size;
	unsigned int		old_size = ifp->if_broot_bytes;

	/*
	 * Block mapping btrees do not support storing zero records; if this
	 * happens, the fork is being changed to FMT_EXTENTS.  Free the broot
	 * and get out.
	 */
	if (new_numrecs == 0)
		return xfs_broot_realloc(ifp, 0);

	new_size = xfs_bmap_broot_space_calc(mp, new_numrecs);

	/* Handle the nop case quietly. */
	if (new_size == old_size)
		return ifp->if_broot;

	if (new_size > old_size) {
		unsigned int	old_numrecs;

		/*
		 * If there wasn't any memory allocated before, just
		 * allocate it now and get out.
		 */
		if (old_size == 0)
			return xfs_broot_realloc(ifp, new_size);

		/*
		 * If there is already an existing if_broot, then we need
		 * to realloc() it and shift the pointers to their new
		 * location.  The records don't change location because
		 * they are kept butted up against the btree block header.
		 */
		old_numrecs = xfs_bmbt_maxrecs(mp, old_size, false);
		broot = xfs_broot_realloc(ifp, new_size);
		ASSERT(xfs_bmap_bmdr_space(broot) <=
			xfs_inode_fork_size(ip, whichfork));
		xfs_bmbt_move_ptrs(mp, broot, old_size, new_size, old_numrecs);
		return broot;
	}

	/*
	 * We're reducing, but not totally eliminating, numrecs.  In this case,
	 * we are shrinking the if_broot buffer, so it must already exist.
	 */
	ASSERT(ifp->if_broot != NULL && old_size > 0 && new_size > 0);

	/*
	 * Shrink the btree root by moving the bmbt pointers, since they are
	 * not butted up against the btree block header, then reallocating
	 * broot.
	 */
	xfs_bmbt_move_ptrs(mp, ifp->if_broot, old_size, new_size, new_numrecs);
	broot = xfs_broot_realloc(ifp, new_size);
	ASSERT(xfs_bmap_bmdr_space(broot) <=
	       xfs_inode_fork_size(ip, whichfork));
	return broot;
}

static struct xfs_btree_block *
xfs_bmbt_broot_realloc(
	struct xfs_btree_cur	*cur,
	unsigned int		new_numrecs)
{
	return xfs_bmap_broot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork,
			new_numrecs);
}

const struct xfs_btree_ops xfs_bmbt_ops = {
	.name			= "bmap",
	.type			= XFS_BTREE_TYPE_INODE,
@@ -543,6 +653,7 @@ const struct xfs_btree_ops xfs_bmbt_ops = {
	.keys_inorder		= xfs_bmbt_keys_inorder,
	.recs_inorder		= xfs_bmbt_recs_inorder,
	.keys_contiguous	= xfs_bmbt_keys_contiguous,
	.broot_realloc		= xfs_bmbt_broot_realloc,
};

/*
Loading