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

Commit 5b911354 authored by Dave Chinner's avatar Dave Chinner
Browse files

Merge branch 'xfs-4.7-optimise-inline-symlinks' into for-next

parents d6bd9615 30ee052e
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -4515,7 +4515,6 @@ int readlink_copy(char __user *buffer, int buflen, const char *link)
out:
	return len;
}
EXPORT_SYMBOL(readlink_copy);

/*
 * A helper for ->readlink().  This should be used *ONLY* for symlinks that
+3 −6
Original line number Diff line number Diff line
@@ -257,15 +257,12 @@ xfs_dir2_block_to_sf(
	 *
	 * Convert the inode to local format and copy the data in.
	 */
	dp->i_df.if_flags &= ~XFS_IFEXTENTS;
	dp->i_df.if_flags |= XFS_IFINLINE;
	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
	ASSERT(dp->i_df.if_bytes == 0);
	xfs_idata_realloc(dp, size, XFS_DATA_FORK);
	xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size);
	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
	dp->i_d.di_size = size;

	logflags |= XFS_ILOG_DDATA;
	memcpy(dp->i_df.if_u1.if_data, dst, size);
	dp->i_d.di_size = size;
	xfs_dir2_sf_check(args);
out:
	xfs_trans_log_inode(args->trans, dp, logflags);
+44 −18
Original line number Diff line number Diff line
@@ -231,6 +231,48 @@ xfs_iformat_fork(
	return error;
}

void
xfs_init_local_fork(
	struct xfs_inode	*ip,
	int			whichfork,
	const void		*data,
	int			size)
{
	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
	int			mem_size = size, real_size = 0;
	bool			zero_terminate;

	/*
	 * If we are using the local fork to store a symlink body we need to
	 * zero-terminate it so that we can pass it back to the VFS directly.
	 * Overallocate the in-memory fork by one for that and add a zero
	 * to terminate it below.
	 */
	zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
	if (zero_terminate)
		mem_size++;

	if (size == 0)
		ifp->if_u1.if_data = NULL;
	else if (mem_size <= sizeof(ifp->if_u2.if_inline_data))
		ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
	else {
		real_size = roundup(mem_size, 4);
		ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS);
	}

	if (size) {
		memcpy(ifp->if_u1.if_data, data, size);
		if (zero_terminate)
			ifp->if_u1.if_data[size] = '\0';
	}

	ifp->if_bytes = size;
	ifp->if_real_bytes = real_size;
	ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
	ifp->if_flags |= XFS_IFINLINE;
}

/*
 * The file is in-lined in the on-disk inode.
 * If it fits into if_inline_data, then copy
@@ -248,8 +290,6 @@ xfs_iformat_local(
	int		whichfork,
	int		size)
{
	xfs_ifork_t	*ifp;
	int		real_size;

	/*
	 * If the size is unreasonable, then something
@@ -265,22 +305,8 @@ xfs_iformat_local(
				     ip->i_mount, dip);
		return -EFSCORRUPTED;
	}
	ifp = XFS_IFORK_PTR(ip, whichfork);
	real_size = 0;
	if (size == 0)
		ifp->if_u1.if_data = NULL;
	else if (size <= sizeof(ifp->if_u2.if_inline_data))
		ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
	else {
		real_size = roundup(size, 4);
		ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS);
	}
	ifp->if_bytes = size;
	ifp->if_real_bytes = real_size;
	if (size)
		memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size);
	ifp->if_flags &= ~XFS_IFEXTENTS;
	ifp->if_flags |= XFS_IFINLINE;

	xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ void xfs_iroot_realloc(struct xfs_inode *, int, int);
int		xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int);
int		xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *,
				  int);
void		xfs_init_local_fork(struct xfs_inode *, int, const void *, int);

struct xfs_bmbt_rec_host *
		xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t);
+1 −0
Original line number Diff line number Diff line
@@ -2840,6 +2840,7 @@ xfs_rename_alloc_whiteout(
	 * and flag it as linkable.
	 */
	drop_nlink(VFS_I(tmpfile));
	xfs_setup_iops(tmpfile);
	xfs_finish_inode_setup(tmpfile);
	VFS_I(tmpfile)->i_state |= I_LINKABLE;

Loading