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

Commit 232c2f5c authored by Dave Chinner's avatar Dave Chinner
Browse files

Merge branch 'xfs-filestreams-lookup' into for-next

parents fdd3a2ae b94acd47
Loading
Loading
Loading
Loading
+117 −85
Original line number Diff line number Diff line
@@ -3515,6 +3515,67 @@ xfs_bmap_adjacent(
#undef ISVALID
}

static int
xfs_bmap_longest_free_extent(
	struct xfs_trans	*tp,
	xfs_agnumber_t		ag,
	xfs_extlen_t		*blen,
	int			*notinit)
{
	struct xfs_mount	*mp = tp->t_mountp;
	struct xfs_perag	*pag;
	xfs_extlen_t		longest;
	int			error = 0;

	pag = xfs_perag_get(mp, ag);
	if (!pag->pagf_init) {
		error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK);
		if (error)
			goto out;

		if (!pag->pagf_init) {
			*notinit = 1;
			goto out;
		}
	}

	longest = xfs_alloc_longest_free_extent(mp, pag);
	if (*blen < longest)
		*blen = longest;

out:
	xfs_perag_put(pag);
	return error;
}

static void
xfs_bmap_select_minlen(
	struct xfs_bmalloca	*ap,
	struct xfs_alloc_arg	*args,
	xfs_extlen_t		*blen,
	int			notinit)
{
	if (notinit || *blen < ap->minlen) {
		/*
		 * Since we did a BUF_TRYLOCK above, it is possible that
		 * there is space for this request.
		 */
		args->minlen = ap->minlen;
	} else if (*blen < args->maxlen) {
		/*
		 * If the best seen length is less than the request length,
		 * use the best as the minimum.
		 */
		args->minlen = *blen;
	} else {
		/*
		 * Otherwise we've seen an extent as big as maxlen, use that
		 * as the minimum.
		 */
		args->minlen = args->maxlen;
	}
}

STATIC int
xfs_bmap_btalloc_nullfb(
	struct xfs_bmalloca	*ap,
@@ -3522,111 +3583,74 @@ xfs_bmap_btalloc_nullfb(
	xfs_extlen_t		*blen)
{
	struct xfs_mount	*mp = ap->ip->i_mount;
	struct xfs_perag	*pag;
	xfs_agnumber_t		ag, startag;
	int			notinit = 0;
	int			error;

	if (ap->userdata && xfs_inode_is_filestream(ap->ip))
		args->type = XFS_ALLOCTYPE_NEAR_BNO;
	else
	args->type = XFS_ALLOCTYPE_START_BNO;
	args->total = ap->total;

	/*
	 * Search for an allocation group with a single extent large enough
	 * for the request.  If one isn't found, then adjust the minimum
	 * allocation size to the largest space found.
	 */
	startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
	if (startag == NULLAGNUMBER)
		startag = ag = 0;

	pag = xfs_perag_get(mp, ag);
	while (*blen < args->maxlen) {
		if (!pag->pagf_init) {
			error = xfs_alloc_pagf_init(mp, args->tp, ag,
						    XFS_ALLOC_FLAG_TRYLOCK);
			if (error) {
				xfs_perag_put(pag);
		error = xfs_bmap_longest_free_extent(args->tp, ag, blen,
						     &notinit);
		if (error)
			return error;

		if (++ag == mp->m_sb.sb_agcount)
			ag = 0;
		if (ag == startag)
			break;
	}

	xfs_bmap_select_minlen(ap, args, blen, notinit);
	return 0;
}

		/*
		 * See xfs_alloc_fix_freelist...
		 */
		if (pag->pagf_init) {
			xfs_extlen_t	longest;
			longest = xfs_alloc_longest_free_extent(mp, pag);
			if (*blen < longest)
				*blen = longest;
		} else
			notinit = 1;
STATIC int
xfs_bmap_btalloc_filestreams(
	struct xfs_bmalloca	*ap,
	struct xfs_alloc_arg	*args,
	xfs_extlen_t		*blen)
{
	struct xfs_mount	*mp = ap->ip->i_mount;
	xfs_agnumber_t		ag;
	int			notinit = 0;
	int			error;

		if (xfs_inode_is_filestream(ap->ip)) {
			if (*blen >= args->maxlen)
				break;
	args->type = XFS_ALLOCTYPE_NEAR_BNO;
	args->total = ap->total;

			if (ap->userdata) {
				/*
				 * If startag is an invalid AG, we've
				 * come here once before and
				 * xfs_filestream_new_ag picked the
				 * best currently available.
				 *
				 * Don't continue looping, since we
				 * could loop forever.
				 */
				if (startag == NULLAGNUMBER)
					break;
	ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
	if (ag == NULLAGNUMBER)
		ag = 0;

	error = xfs_bmap_longest_free_extent(args->tp, ag, blen, &notinit);
	if (error)
		return error;

	if (*blen < args->maxlen) {
		error = xfs_filestream_new_ag(ap, &ag);
				xfs_perag_put(pag);
		if (error)
			return error;

				/* loop again to set 'blen'*/
				startag = NULLAGNUMBER;
				pag = xfs_perag_get(mp, ag);
				continue;
			}
		}
		if (++ag == mp->m_sb.sb_agcount)
			ag = 0;
		if (ag == startag)
			break;
		xfs_perag_put(pag);
		pag = xfs_perag_get(mp, ag);
		error = xfs_bmap_longest_free_extent(args->tp, ag, blen,
						     &notinit);
		if (error)
			return error;

	}
	xfs_perag_put(pag);

	/*
	 * Since the above loop did a BUF_TRYLOCK, it is
	 * possible that there is space for this request.
	 */
	if (notinit || *blen < ap->minlen)
		args->minlen = ap->minlen;
	/*
	 * If the best seen length is less than the request
	 * length, use the best as the minimum.
	 */
	else if (*blen < args->maxlen)
		args->minlen = *blen;
	/*
	 * Otherwise we've seen an extent as big as maxlen,
	 * use that as the minimum.
	 */
	else
		args->minlen = args->maxlen;
	xfs_bmap_select_minlen(ap, args, blen, notinit);

	/*
	 * set the failure fallback case to look in the selected
	 * AG as the stream may have moved.
	 * Set the failure fallback case to look in the selected AG as stream
	 * may have moved.
	 */
	if (xfs_inode_is_filestream(ap->ip))
	ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);

	return 0;
}

@@ -3706,6 +3730,14 @@ xfs_bmap_btalloc(
	args.firstblock = *ap->firstblock;
	blen = 0;
	if (nullfb) {
		/*
		 * Search for an allocation group with a single extent large
		 * enough for the request.  If one isn't found, then adjust
		 * the minimum allocation size to the largest space found.
		 */
		if (ap->userdata && xfs_inode_is_filestream(ap->ip))
			error = xfs_bmap_btalloc_filestreams(ap, &args, &blen);
		else
			error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
		if (error)
			return error;
+147 −537

File changed.

Preview size limit exceeded, changes collapsed.

+2 −32
Original line number Diff line number Diff line
@@ -20,50 +20,20 @@

struct xfs_mount;
struct xfs_inode;
struct xfs_perag;
struct xfs_bmalloca;

#ifdef XFS_FILESTREAMS_TRACE
#define XFS_FSTRM_KTRACE_INFO		1
#define XFS_FSTRM_KTRACE_AGSCAN		2
#define XFS_FSTRM_KTRACE_AGPICK1	3
#define XFS_FSTRM_KTRACE_AGPICK2	4
#define XFS_FSTRM_KTRACE_UPDATE		5
#define XFS_FSTRM_KTRACE_FREE		6
#define	XFS_FSTRM_KTRACE_ITEM_LOOKUP	7
#define	XFS_FSTRM_KTRACE_ASSOCIATE	8
#define	XFS_FSTRM_KTRACE_MOVEAG		9
#define	XFS_FSTRM_KTRACE_ORPHAN		10

#define XFS_FSTRM_KTRACE_SIZE	16384
extern ktrace_t *xfs_filestreams_trace_buf;

#endif

/* allocation selection flags */
typedef enum xfs_fstrm_alloc {
	XFS_PICK_USERDATA = 1,
	XFS_PICK_LOWSPACE = 2,
} xfs_fstrm_alloc_t;

/* prototypes for filestream.c */
int xfs_filestream_init(void);
void xfs_filestream_uninit(void);
int xfs_filestream_mount(struct xfs_mount *mp);
void xfs_filestream_unmount(struct xfs_mount *mp);
xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip);
int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip);
void xfs_filestream_deassociate(struct xfs_inode *ip);
xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip);
int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp);
int xfs_filestream_peek_ag(struct xfs_mount *mp, xfs_agnumber_t agno);


/* filestreams for the inode? */
static inline int
xfs_inode_is_filestream(
	struct xfs_inode	*ip)
{
	return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) ||
		xfs_iflags_test(ip, XFS_IFILESTREAM) ||
		(ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM);
}

+1 −34
Original line number Diff line number Diff line
@@ -655,7 +655,6 @@ xfs_ialloc(
	uint		flags;
	int		error;
	timespec_t	tv;
	int		filestreams = 0;

	/*
	 * Call the space management code to pick
@@ -772,13 +771,6 @@ xfs_ialloc(
		flags |= XFS_ILOG_DEV;
		break;
	case S_IFREG:
		/*
		 * we can't set up filestreams until after the VFS inode
		 * is set up properly.
		 */
		if (pip && xfs_inode_is_filestream(pip))
			filestreams = 1;
		/* fall through */
	case S_IFDIR:
		if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
			uint	di_flags = 0;
@@ -844,15 +836,6 @@ xfs_ialloc(
	/* now that we have an i_mode we can setup inode ops and unlock */
	xfs_setup_inode(ip);

	/* now we have set up the vfs inode we can associate the filestream */
	if (filestreams) {
		error = xfs_filestream_associate(pip, ip);
		if (error < 0)
			return -error;
		if (!error)
			xfs_iflags_set(ip, XFS_IFILESTREAM);
	}

	*ipp = ip;
	return 0;
}
@@ -1698,16 +1681,6 @@ xfs_release(
	if (!XFS_FORCED_SHUTDOWN(mp)) {
		int truncated;

		/*
		 * If we are using filestreams, and we have an unlinked
		 * file that we are processing the last close on, then nothing
		 * will be able to reopen and write to this file. Purge this
		 * inode from the filestreams cache so that it doesn't delay
		 * teardown of the inode.
		 */
		if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip))
			xfs_filestream_deassociate(ip);

		/*
		 * If we previously truncated this file and removed old data
		 * in the process, we want to initiate "early" writeout on
@@ -2664,13 +2637,7 @@ xfs_remove(
	if (error)
		goto std_return;

	/*
	 * If we are using filestreams, kill the stream association.
	 * If the file is still open it may get a new one but that
	 * will get killed on last close in xfs_close() so we don't
	 * have to worry about that.
	 */
	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
	if (is_dir && xfs_inode_is_filestream(ip))
		xfs_filestream_deassociate(ip);

	return 0;
+1 −3
Original line number Diff line number Diff line
@@ -209,7 +209,6 @@ xfs_get_initial_prid(struct xfs_inode *dp)
#define XFS_ISTALE		(1 << 1) /* inode has been staled */
#define XFS_IRECLAIMABLE	(1 << 2) /* inode can be reclaimed */
#define XFS_INEW		(1 << 3) /* inode has just been allocated */
#define XFS_IFILESTREAM		(1 << 4) /* inode is in a filestream dir. */
#define XFS_ITRUNCATED		(1 << 5) /* truncated down so flush-on-close */
#define XFS_IDIRTY_RELEASE	(1 << 6) /* dirty release already seen */
#define __XFS_IFLOCK_BIT	7	 /* inode is being flushed right now */
@@ -225,8 +224,7 @@ xfs_get_initial_prid(struct xfs_inode *dp)
 */
#define XFS_IRECLAIM_RESET_FLAGS	\
	(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
	 XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \
	 XFS_IFILESTREAM);
	 XFS_IDIRTY_RELEASE | XFS_ITRUNCATED)

/*
 * Synchronize processes attempting to flush the in-core inode back to disk.
Loading