mirror of
https://github.com/torvalds/linux.git
synced 2024-12-05 10:32:35 +00:00
8ffa90e114
Refactor xfs_getfsmap to improve its performance: instead of indirectly
calling a function that copies one record to userspace at a time, create
a shadow buffer in the kernel and copy the whole array once at the end.
On the author's computer, this reduces the runtime on his /home by ~20%.
This also eliminates a deadlock when running GETFSMAP against the
realtime device. The current code locks the rtbitmap to create
fsmappings and copies them into userspace, having not released the
rtbitmap lock. If the userspace buffer is an mmap of a sparse file that
itself resides on the realtime device, the write page fault will recurse
into the fs for allocation, which will deadlock on the rtbitmap lock.
Fixes: 4c934c7dd6
("xfs: report realtime space information via the rtbitmap")
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
36 lines
1.0 KiB
C
36 lines
1.0 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2017 Oracle. All Rights Reserved.
|
|
* Author: Darrick J. Wong <darrick.wong@oracle.com>
|
|
*/
|
|
#ifndef __XFS_FSMAP_H__
|
|
#define __XFS_FSMAP_H__
|
|
|
|
struct fsmap;
|
|
|
|
/* internal fsmap representation */
|
|
struct xfs_fsmap {
|
|
dev_t fmr_device; /* device id */
|
|
uint32_t fmr_flags; /* mapping flags */
|
|
uint64_t fmr_physical; /* device offset of segment */
|
|
uint64_t fmr_owner; /* owner id */
|
|
xfs_fileoff_t fmr_offset; /* file offset of segment */
|
|
xfs_filblks_t fmr_length; /* length of segment, blocks */
|
|
};
|
|
|
|
struct xfs_fsmap_head {
|
|
uint32_t fmh_iflags; /* control flags */
|
|
uint32_t fmh_oflags; /* output flags */
|
|
unsigned int fmh_count; /* # of entries in array incl. input */
|
|
unsigned int fmh_entries; /* # of entries filled in (output). */
|
|
|
|
struct xfs_fsmap fmh_keys[2]; /* low and high keys */
|
|
};
|
|
|
|
void xfs_fsmap_to_internal(struct xfs_fsmap *dest, struct fsmap *src);
|
|
|
|
int xfs_getfsmap(struct xfs_mount *mp, struct xfs_fsmap_head *head,
|
|
struct fsmap *out_recs);
|
|
|
|
#endif /* __XFS_FSMAP_H__ */
|