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

Merge tag 'xfs-6.10-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Chandan Babu:

 - Fix a livelock by dropping an xfarray sortinfo folio when an error
   is encountered

 - During extended attribute operations, Initialize transaction
   reservation computation based on attribute operation code

 - Relax symbolic link's ondisk verification code to allow symbolic
   links with short remote targets

 - Prevent soft lockups when unmapping file ranges and also during
   remapping blocks during a reflink operation

 - Fix compilation warnings when XFS is built with W=1 option

* tag 'xfs-6.10-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: Add cond_resched to block unmap range and reflink remap path
  xfs: don't open-code u64_to_user_ptr
  xfs: allow symlinks with short remote targets
  xfs: fix xfs_init_attr_trans not handling explicit operation codes
  xfs: drop xfarray sortinfo folio on error
  xfs: Stop using __maybe_unused in xfs_alloc.c
  xfs: Clear W=1 warning in xfs_iwalk_run_callbacks()
parents f26ee67a b0c6bcd5
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -1008,13 +1008,12 @@ xfs_alloc_cur_finish(
	struct xfs_alloc_arg	*args,
	struct xfs_alloc_cur	*acur)
{
	struct xfs_agf __maybe_unused *agf = args->agbp->b_addr;
	int			error;

	ASSERT(acur->cnt && acur->bnolt);
	ASSERT(acur->bno >= acur->rec_bno);
	ASSERT(acur->bno + acur->len <= acur->rec_bno + acur->rec_len);
	ASSERT(acur->rec_bno + acur->rec_len <= be32_to_cpu(agf->agf_length));
	ASSERT(xfs_verify_agbext(args->pag, acur->rec_bno, acur->rec_len));

	error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno,
				      acur->rec_len, acur->bno, acur->len, 0);
@@ -1217,7 +1216,6 @@ STATIC int /* error */
xfs_alloc_ag_vextent_exact(
	xfs_alloc_arg_t	*args)	/* allocation argument structure */
{
	struct xfs_agf __maybe_unused *agf = args->agbp->b_addr;
	struct xfs_btree_cur *bno_cur;/* by block-number btree cursor */
	struct xfs_btree_cur *cnt_cur;/* by count btree cursor */
	int		error;
@@ -1297,7 +1295,7 @@ xfs_alloc_ag_vextent_exact(
	 */
	cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, args->agbp,
					args->pag);
	ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length));
	ASSERT(xfs_verify_agbext(args->pag, args->agbno, args->len));
	error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno,
				      args->len, XFSA_FIXUP_BNO_OK);
	if (error) {
+19 −21
Original line number Diff line number Diff line
@@ -329,26 +329,20 @@ xfs_attr_calc_size(
	return nblks;
}

/* Initialize transaction reservation for attr operations */
void
xfs_init_attr_trans(
	struct xfs_da_args	*args,
	struct xfs_trans_res	*tres,
	unsigned int		*total)
/* Initialize transaction reservation for an xattr set/replace/upsert */
inline struct xfs_trans_res
xfs_attr_set_resv(
	const struct xfs_da_args	*args)
{
	struct xfs_mount		*mp = args->dp->i_mount;
	struct xfs_trans_res		ret = {
		.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
			    M_RES(mp)->tr_attrsetrt.tr_logres * args->total,
		.tr_logcount		= XFS_ATTRSET_LOG_COUNT,
		.tr_logflags		= XFS_TRANS_PERM_LOG_RES,
	};

	if (args->value) {
		tres->tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
				 M_RES(mp)->tr_attrsetrt.tr_logres *
				 args->total;
		tres->tr_logcount = XFS_ATTRSET_LOG_COUNT;
		tres->tr_logflags = XFS_TRANS_PERM_LOG_RES;
		*total = args->total;
	} else {
		*tres = M_RES(mp)->tr_attrrm;
		*total = XFS_ATTRRM_SPACE_RES(mp);
	}
	return ret;
}

/*
@@ -1006,7 +1000,7 @@ xfs_attr_set(
	struct xfs_trans_res	tres;
	int			error, local;
	int			rmt_blks = 0;
	unsigned int		total;
	unsigned int		total = 0;

	ASSERT(!args->trans);

@@ -1033,10 +1027,15 @@ xfs_attr_set(

		if (!local)
			rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);

		tres = xfs_attr_set_resv(args);
		total = args->total;
		break;
	case XFS_ATTRUPDATE_REMOVE:
		XFS_STATS_INC(mp, xs_attr_remove);
		rmt_blks = xfs_attr3_max_rmt_blocks(mp);
		tres = M_RES(mp)->tr_attrrm;
		total = XFS_ATTRRM_SPACE_RES(mp);
		break;
	}

@@ -1044,7 +1043,6 @@ xfs_attr_set(
	 * Root fork attributes can use reserved data blocks for this
	 * operation if necessary
	 */
	xfs_init_attr_trans(args, &tres, &total);
	error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
	if (error)
		return error;
+1 −2
Original line number Diff line number Diff line
@@ -565,8 +565,7 @@ bool xfs_attr_check_namespace(unsigned int attr_flags);
bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
		size_t length);
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
			 unsigned int *total);
struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args);

/*
 * Check to see if the attr should be upgraded from non-existent or shortform to
+1 −0
Original line number Diff line number Diff line
@@ -6383,6 +6383,7 @@ xfs_bunmapi_range(
		error = xfs_defer_finish(tpp);
		if (error)
			goto out;
		cond_resched();
	}
out:
	return error;
+24 −4
Original line number Diff line number Diff line
@@ -374,17 +374,37 @@ xfs_dinode_verify_fork(
	/*
	 * For fork types that can contain local data, check that the fork
	 * format matches the size of local data contained within the fork.
	 *
	 * For all types, check that when the size says the should be in extent
	 * or btree format, the inode isn't claiming it is in local format.
	 */
	if (whichfork == XFS_DATA_FORK) {
		if (S_ISDIR(mode) || S_ISLNK(mode)) {
		/*
		 * A directory small enough to fit in the inode must be stored
		 * in local format.  The directory sf <-> extents conversion
		 * code updates the directory size accordingly.
		 */
		if (S_ISDIR(mode)) {
			if (be64_to_cpu(dip->di_size) <= fork_size &&
			    fork_format != XFS_DINODE_FMT_LOCAL)
				return __this_address;
		}

		/*
		 * A symlink with a target small enough to fit in the inode can
		 * be stored in extents format if xattrs were added (thus
		 * converting the data fork from shortform to remote format)
		 * and then removed.
		 */
		if (S_ISLNK(mode)) {
			if (be64_to_cpu(dip->di_size) <= fork_size &&
			    fork_format != XFS_DINODE_FMT_EXTENTS &&
			    fork_format != XFS_DINODE_FMT_LOCAL)
				return __this_address;
		}

		/*
		 * For all types, check that when the size says the fork should
		 * be in extent or btree format, the inode isn't claiming to be
		 * in local format.
		 */
		if (be64_to_cpu(dip->di_size) > fork_size &&
		    fork_format == XFS_DINODE_FMT_LOCAL)
			return __this_address;
Loading