mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:24:47 +01:00
Zones in the beginning of the address space are typically mapped to higer bandwidth tracks on HDDs than those at the end of the address space. So, in stead of allocating zones "round robin" across the whole address space, always allocate the zone with the lowest index. This increases average write bandwidth for overwrite workloads when less than the full capacity is being used. At ~50% utilization this improves bandwidth for a random file overwrite benchmark with 128MiB files and 256MiB zone capacity by 30%. Running the same benchmark with small 2-8 MiB files at 67% capacity shows no significant difference in performance. Due to heavy fragmentation the whole zone range is in use, greatly limiting the number of free zones with high bw. Signed-off-by: Hans Holmberg <hans.holmberg@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Carlos Maiolino <cem@kernel.org>
121 lines
3.2 KiB
C
121 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _XFS_ZONE_PRIV_H
|
|
#define _XFS_ZONE_PRIV_H
|
|
|
|
struct xfs_open_zone {
|
|
/*
|
|
* Entry in the open zone list and refcount. Protected by
|
|
* zi_open_zones_lock in struct xfs_zone_info.
|
|
*/
|
|
struct list_head oz_entry;
|
|
atomic_t oz_ref;
|
|
|
|
/*
|
|
* oz_allocated is the amount of space already allocated out of the zone
|
|
* and is protected by oz_alloc_lock.
|
|
*
|
|
* For conventional zones it also is the offset of the next write.
|
|
*/
|
|
spinlock_t oz_alloc_lock;
|
|
xfs_rgblock_t oz_allocated;
|
|
|
|
/*
|
|
* oz_written is the number of blocks for which we've received a write
|
|
* completion. oz_written must always be <= oz_allocated and is
|
|
* protected by the ILOCK of the rmap inode.
|
|
*/
|
|
xfs_rgblock_t oz_written;
|
|
|
|
/*
|
|
* Write hint (data temperature) assigned to this zone, or
|
|
* WRITE_LIFE_NOT_SET if none was set.
|
|
*/
|
|
enum rw_hint oz_write_hint;
|
|
|
|
/*
|
|
* Is this open zone used for garbage collection? There can only be a
|
|
* single open GC zone, which is pointed to by zi_open_gc_zone in
|
|
* struct xfs_zone_info. Constant over the life time of an open zone.
|
|
*/
|
|
bool oz_is_gc;
|
|
|
|
/*
|
|
* Pointer to the RT groups structure for this open zone. Constant over
|
|
* the life time of an open zone.
|
|
*/
|
|
struct xfs_rtgroup *oz_rtg;
|
|
|
|
struct rcu_head oz_rcu;
|
|
};
|
|
|
|
/*
|
|
* Number of bitmap buckets to track reclaimable zones. There are 10 buckets
|
|
* so that each 10% of the usable capacity get their own bucket and GC can
|
|
* only has to walk the bitmaps of the lesser used zones if there are any.
|
|
*/
|
|
#define XFS_ZONE_USED_BUCKETS 10u
|
|
|
|
struct xfs_zone_info {
|
|
/*
|
|
* List of pending space reservations:
|
|
*/
|
|
spinlock_t zi_reservation_lock;
|
|
struct list_head zi_reclaim_reservations;
|
|
|
|
/*
|
|
* List and number of open zones:
|
|
*/
|
|
spinlock_t zi_open_zones_lock;
|
|
struct list_head zi_open_zones;
|
|
unsigned int zi_nr_open_zones;
|
|
|
|
/*
|
|
* Free zone search cursor and number of free zones:
|
|
*/
|
|
atomic_t zi_nr_free_zones;
|
|
|
|
/*
|
|
* Wait queue to wait for free zones or open zone resources to become
|
|
* available:
|
|
*/
|
|
wait_queue_head_t zi_zone_wait;
|
|
|
|
/*
|
|
* Pointer to the GC thread, and the current open zone used by GC
|
|
* (if any).
|
|
*
|
|
* zi_open_gc_zone is mostly private to the GC thread, but can be read
|
|
* for debugging from other threads, in which case zi_open_zones_lock
|
|
* must be taken to access it.
|
|
*/
|
|
struct task_struct *zi_gc_thread;
|
|
struct xfs_open_zone *zi_open_gc_zone;
|
|
|
|
/*
|
|
* List of zones that need a reset:
|
|
*/
|
|
spinlock_t zi_reset_list_lock;
|
|
struct xfs_group *zi_reset_list;
|
|
|
|
/*
|
|
* A set of bitmaps to bucket-sort reclaimable zones by used blocks to help
|
|
* garbage collection to quickly find the best candidate for reclaim.
|
|
*/
|
|
spinlock_t zi_used_buckets_lock;
|
|
unsigned int zi_used_bucket_entries[XFS_ZONE_USED_BUCKETS];
|
|
unsigned long *zi_used_bucket_bitmap[XFS_ZONE_USED_BUCKETS];
|
|
|
|
};
|
|
|
|
struct xfs_open_zone *xfs_open_zone(struct xfs_mount *mp,
|
|
enum rw_hint write_hint, bool is_gc);
|
|
|
|
int xfs_zone_gc_reset_sync(struct xfs_rtgroup *rtg);
|
|
bool xfs_zoned_need_gc(struct xfs_mount *mp);
|
|
bool xfs_zoned_have_reclaimable(struct xfs_zone_info *zi);
|
|
int xfs_zone_gc_mount(struct xfs_mount *mp);
|
|
void xfs_zone_gc_unmount(struct xfs_mount *mp);
|
|
|
|
void xfs_zoned_resv_wake_all(struct xfs_mount *mp);
|
|
|
|
#endif /* _XFS_ZONE_PRIV_H */
|