2018-06-06 10:42:14 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2016-08-03 09:12:25 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 Oracle. All Rights Reserved.
|
|
|
|
* Author: Darrick J. Wong <darrick.wong@oracle.com>
|
|
|
|
*/
|
|
|
|
#ifndef __XFS_DEFER_H__
|
|
|
|
#define __XFS_DEFER_H__
|
|
|
|
|
|
|
|
struct xfs_defer_op_type;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save a log intent item and a list of extents, so that we can replay
|
|
|
|
* whatever action had to happen to the extent list and file the log done
|
|
|
|
* item.
|
|
|
|
*/
|
|
|
|
struct xfs_defer_pending {
|
|
|
|
const struct xfs_defer_op_type *dfp_type; /* function pointers */
|
|
|
|
struct list_head dfp_list; /* pending items */
|
|
|
|
void *dfp_intent; /* log intent item */
|
2016-08-30 11:51:39 +08:00
|
|
|
void *dfp_done; /* log done item */
|
2016-08-03 09:12:25 +08:00
|
|
|
struct list_head dfp_work; /* work items */
|
|
|
|
unsigned int dfp_count; /* # extent items */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Header for deferred operation list.
|
|
|
|
*
|
|
|
|
* dop_low is used by the allocator to activate the lowspace algorithm -
|
|
|
|
* when free space is running low the extent allocator may choose to
|
|
|
|
* allocate an extent from an AG without leaving sufficient space for
|
|
|
|
* a btree split when inserting the new extent. In this case the allocator
|
|
|
|
* will enable the lowspace algorithm which is supposed to allow further
|
|
|
|
* allocations (such as btree splits and newroots) to allocate from
|
|
|
|
* sequential AGs. In order to avoid locking AGs out of order the lowspace
|
|
|
|
* algorithm will start searching for free space from AG 0. If the correct
|
|
|
|
* transaction reservations have been made then this algorithm will eventually
|
|
|
|
* find all the space it needs.
|
|
|
|
*/
|
|
|
|
enum xfs_defer_ops_type {
|
2016-10-04 00:11:28 +08:00
|
|
|
XFS_DEFER_OPS_TYPE_BMAP,
|
2016-10-04 00:11:22 +08:00
|
|
|
XFS_DEFER_OPS_TYPE_REFCOUNT,
|
2016-08-03 10:11:01 +08:00
|
|
|
XFS_DEFER_OPS_TYPE_RMAP,
|
2016-08-03 09:14:35 +08:00
|
|
|
XFS_DEFER_OPS_TYPE_FREE,
|
2018-05-08 08:38:47 +08:00
|
|
|
XFS_DEFER_OPS_TYPE_AGFL_FREE,
|
2016-08-03 09:12:25 +08:00
|
|
|
XFS_DEFER_OPS_TYPE_MAX,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */
|
2017-12-08 11:07:02 +08:00
|
|
|
#define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */
|
2016-08-03 09:12:25 +08:00
|
|
|
|
|
|
|
struct xfs_defer_ops {
|
|
|
|
struct list_head dop_intake; /* unlogged pending work */
|
|
|
|
struct list_head dop_pending; /* logged pending work */
|
|
|
|
|
2017-12-08 11:07:02 +08:00
|
|
|
/* relog these with each roll */
|
2016-08-03 09:12:25 +08:00
|
|
|
struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES];
|
2017-12-08 11:07:02 +08:00
|
|
|
struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS];
|
2018-07-25 04:43:11 +08:00
|
|
|
|
|
|
|
bool dop_low; /* alloc in low mode */
|
2016-08-03 09:12:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
|
|
|
|
struct list_head *h);
|
2017-08-29 01:21:04 +08:00
|
|
|
int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop);
|
2016-08-03 09:12:25 +08:00
|
|
|
void xfs_defer_cancel(struct xfs_defer_ops *dop);
|
2018-07-12 13:26:33 +08:00
|
|
|
void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
|
2016-08-03 09:12:25 +08:00
|
|
|
bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
|
2017-08-29 01:21:03 +08:00
|
|
|
int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
|
2017-12-08 11:07:02 +08:00
|
|
|
int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);
|
2016-08-03 09:12:25 +08:00
|
|
|
|
|
|
|
/* Description of a deferred type. */
|
|
|
|
struct xfs_defer_op_type {
|
|
|
|
enum xfs_defer_ops_type type;
|
|
|
|
unsigned int max_items;
|
|
|
|
void (*abort_intent)(void *);
|
|
|
|
void *(*create_done)(struct xfs_trans *, void *, unsigned int);
|
|
|
|
int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *,
|
|
|
|
struct list_head *, void *, void **);
|
|
|
|
void (*finish_cleanup)(struct xfs_trans *, void *, int);
|
|
|
|
void (*cancel_item)(struct list_head *);
|
|
|
|
int (*diff_items)(void *, struct list_head *, struct list_head *);
|
|
|
|
void *(*create_intent)(struct xfs_trans *, uint);
|
|
|
|
void (*log_item)(struct xfs_trans *, void *, struct list_head *);
|
|
|
|
};
|
|
|
|
|
|
|
|
void xfs_defer_init_op_type(const struct xfs_defer_op_type *type);
|
|
|
|
|
|
|
|
#endif /* __XFS_DEFER_H__ */
|