mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
xfs: clean up the rtbitmap code [v4.2 3/8]
Here are some cleanups and reorganization of the realtime bitmap code to share more of that code between userspace and the kernel. With a bit of luck, this should all go splendidly. Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZtX/YwAKCRBKO3ySh0YR plcbAP9AlHyTFF8Ba3ELFh9XD3CIAqi7i5mKVn4p8klXJI5E1wEAw0g315kuIJWz v+6qMd7fVCRIhuEwni6Pw/obkclMogA= =+Wof -----END PGP SIGNATURE----- Merge tag 'rtbitmap-cleanups-6.12_2024-09-02' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.12-mergeA xfs: clean up the rtbitmap code [v4.2 3/8] Here are some cleanups and reorganization of the realtime bitmap code to share more of that code between userspace and the kernel. With a bit of luck, this should all go splendidly. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'rtbitmap-cleanups-6.12_2024-09-02' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: push transaction join out of xfs_rtbitmap_lock and xfs_rtgroup_lock xfs: factor out rtbitmap/summary initialization helpers xfs: factor out a xfs_last_rt_bmblock helper xfs: factor out a xfs_growfs_rt_bmblock helper xfs: push the calls to xfs_rtallocate_range out to xfs_bmap_rtalloc xfs: cleanup the calling convention for xfs_rtpick_extent xfs: add bounds checking to xfs_rt{bitmap,summary}_read_buf xfs: assert a valid limit in xfs_rtfind_forw xfs: remove the limit argument to xfs_rtfind_back xfs: make the RT rsum_cache mandatory xfs: factor out a xfs_validate_rt_geometry helper xfs: remove xfs_validate_rtextents
This commit is contained in:
commit
0879dee5ce
|
|
@ -5376,7 +5376,8 @@ xfs_bmap_del_extent_real(
|
|||
*/
|
||||
if (!(tp->t_flags & XFS_TRANS_RTBITMAP_LOCKED)) {
|
||||
tp->t_flags |= XFS_TRANS_RTBITMAP_LOCKED;
|
||||
xfs_rtbitmap_lock(tp, mp);
|
||||
xfs_rtbitmap_lock(mp);
|
||||
xfs_rtbitmap_trans_join(tp);
|
||||
}
|
||||
error = xfs_rtfree_blocks(tp, del->br_startblock,
|
||||
del->br_blockcount);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
#include "xfs_mount.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_trans_space.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_error.h"
|
||||
|
|
@ -69,7 +71,7 @@ xfs_rtbuf_cache_relse(
|
|||
* Get a buffer for the bitmap or summary file block specified.
|
||||
* The buffer is returned read and locked.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
xfs_rtbuf_get(
|
||||
struct xfs_rtalloc_args *args,
|
||||
xfs_fileoff_t block, /* block number in bitmap or summary */
|
||||
|
|
@ -138,15 +140,43 @@ xfs_rtbuf_get(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xfs_rtbitmap_read_buf(
|
||||
struct xfs_rtalloc_args *args,
|
||||
xfs_fileoff_t block)
|
||||
{
|
||||
struct xfs_mount *mp = args->mp;
|
||||
|
||||
if (XFS_IS_CORRUPT(mp, block >= mp->m_sb.sb_rbmblocks)) {
|
||||
xfs_rt_mark_sick(mp, XFS_SICK_RT_BITMAP);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
return xfs_rtbuf_get(args, block, 0);
|
||||
}
|
||||
|
||||
int
|
||||
xfs_rtsummary_read_buf(
|
||||
struct xfs_rtalloc_args *args,
|
||||
xfs_fileoff_t block)
|
||||
{
|
||||
struct xfs_mount *mp = args->mp;
|
||||
|
||||
if (XFS_IS_CORRUPT(mp, block >= XFS_B_TO_FSB(mp, mp->m_rsumsize))) {
|
||||
xfs_rt_mark_sick(args->mp, XFS_SICK_RT_SUMMARY);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
return xfs_rtbuf_get(args, block, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Searching backward from start to limit, find the first block whose
|
||||
* allocated/free state is different from start's.
|
||||
* Searching backward from start find the first block whose allocated/free state
|
||||
* is different from start's.
|
||||
*/
|
||||
int
|
||||
xfs_rtfind_back(
|
||||
struct xfs_rtalloc_args *args,
|
||||
xfs_rtxnum_t start, /* starting rtext to look at */
|
||||
xfs_rtxnum_t limit, /* last rtext to look at */
|
||||
xfs_rtxnum_t *rtx) /* out: start rtext found */
|
||||
{
|
||||
struct xfs_mount *mp = args->mp;
|
||||
|
|
@ -175,7 +205,7 @@ xfs_rtfind_back(
|
|||
*/
|
||||
word = xfs_rtx_to_rbmword(mp, start);
|
||||
bit = (int)(start & (XFS_NBWORD - 1));
|
||||
len = start - limit + 1;
|
||||
len = start + 1;
|
||||
/*
|
||||
* Compute match value, based on the bit at start: if 1 (free)
|
||||
* then all-ones, else all-zeroes.
|
||||
|
|
@ -316,6 +346,8 @@ xfs_rtfind_forw(
|
|||
xfs_rtword_t incore;
|
||||
unsigned int word; /* word number in the buffer */
|
||||
|
||||
ASSERT(start <= limit);
|
||||
|
||||
/*
|
||||
* Compute and read in starting bitmap block for starting block.
|
||||
*/
|
||||
|
|
@ -698,7 +730,7 @@ xfs_rtfree_range(
|
|||
* We need to find the beginning and end of the extent so we can
|
||||
* properly update the summary.
|
||||
*/
|
||||
error = xfs_rtfind_back(args, start, 0, &preblock);
|
||||
error = xfs_rtfind_back(args, start, &preblock);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
|
@ -1169,23 +1201,25 @@ xfs_rtsummary_wordcount(
|
|||
return XFS_FSB_TO_B(mp, blocks) >> XFS_WORDLOG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock both realtime free space metadata inodes for a freespace update. If a
|
||||
* transaction is given, the inodes will be joined to the transaction and the
|
||||
* ILOCKs will be released on transaction commit.
|
||||
*/
|
||||
/* Lock both realtime free space metadata inodes for a freespace update. */
|
||||
void
|
||||
xfs_rtbitmap_lock(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
|
||||
if (tp)
|
||||
xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
|
||||
|
||||
xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM);
|
||||
if (tp)
|
||||
xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Join both realtime free space metadata inodes to the transaction. The
|
||||
* ILOCKs will be released on transaction commit.
|
||||
*/
|
||||
void
|
||||
xfs_rtbitmap_trans_join(
|
||||
struct xfs_trans *tp)
|
||||
{
|
||||
xfs_trans_ijoin(tp, tp->t_mountp->m_rbmip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, tp->t_mountp->m_rsumip, XFS_ILOCK_EXCL);
|
||||
}
|
||||
|
||||
/* Unlock both realtime free space metadata inodes after a freespace update. */
|
||||
|
|
@ -1225,3 +1259,127 @@ xfs_rtbitmap_unlock_shared(
|
|||
if (rbmlock_flags & XFS_RBMLOCK_BITMAP)
|
||||
xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_rtfile_alloc_blocks(
|
||||
struct xfs_inode *ip,
|
||||
xfs_fileoff_t offset_fsb,
|
||||
xfs_filblks_t count_fsb,
|
||||
struct xfs_bmbt_irec *map)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
int nmap = 1;
|
||||
int error;
|
||||
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc,
|
||||
XFS_GROWFSRT_SPACE_RES(mp, count_fsb), 0, 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
|
||||
error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK,
|
||||
XFS_IEXT_ADD_NOSPLIT_CNT);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
|
||||
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
|
||||
XFS_BMAPI_METADATA, 0, map, &nmap);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
|
||||
return xfs_trans_commit(tp);
|
||||
|
||||
out_trans_cancel:
|
||||
xfs_trans_cancel(tp);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Get a buffer for the block. */
|
||||
static int
|
||||
xfs_rtfile_initialize_block(
|
||||
struct xfs_inode *ip,
|
||||
xfs_fsblock_t fsbno,
|
||||
void *data)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_buf *bp;
|
||||
const size_t copylen = mp->m_blockwsize << XFS_WORDLOG;
|
||||
enum xfs_blft buf_type;
|
||||
int error;
|
||||
|
||||
if (ip == mp->m_rsumip)
|
||||
buf_type = XFS_BLFT_RTSUMMARY_BUF;
|
||||
else
|
||||
buf_type = XFS_BLFT_RTBITMAP_BUF;
|
||||
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero, 0, 0, 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
XFS_FSB_TO_DADDR(mp, fsbno), mp->m_bsize, 0, &bp);
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp);
|
||||
return error;
|
||||
}
|
||||
|
||||
xfs_trans_buf_set_type(tp, bp, buf_type);
|
||||
bp->b_ops = &xfs_rtbuf_ops;
|
||||
if (data)
|
||||
memcpy(bp->b_addr, data, copylen);
|
||||
else
|
||||
memset(bp->b_addr, 0, copylen);
|
||||
xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
|
||||
return xfs_trans_commit(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space to the bitmap or summary file, and zero it, for growfs.
|
||||
* @data must be a contiguous buffer large enough to fill all blocks in the
|
||||
* file; or NULL to initialize the contents to zeroes.
|
||||
*/
|
||||
int
|
||||
xfs_rtfile_initialize_blocks(
|
||||
struct xfs_inode *ip, /* inode (bitmap/summary) */
|
||||
xfs_fileoff_t offset_fsb, /* offset to start from */
|
||||
xfs_fileoff_t end_fsb, /* offset to allocate to */
|
||||
void *data) /* data to fill the blocks */
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
const size_t copylen = mp->m_blockwsize << XFS_WORDLOG;
|
||||
|
||||
while (offset_fsb < end_fsb) {
|
||||
struct xfs_bmbt_irec map;
|
||||
xfs_filblks_t i;
|
||||
int error;
|
||||
|
||||
error = xfs_rtfile_alloc_blocks(ip, offset_fsb,
|
||||
end_fsb - offset_fsb, &map);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Now we need to clear the allocated blocks.
|
||||
*
|
||||
* Do this one block per transaction, to keep it simple.
|
||||
*/
|
||||
for (i = 0; i < map.br_blockcount; i++) {
|
||||
error = xfs_rtfile_initialize_block(ip,
|
||||
map.br_startblock + i, data);
|
||||
if (error)
|
||||
return error;
|
||||
if (data)
|
||||
data += copylen;
|
||||
}
|
||||
|
||||
offset_fsb = map.br_startoff + map.br_blockcount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,30 +293,12 @@ typedef int (*xfs_rtalloc_query_range_fn)(
|
|||
|
||||
#ifdef CONFIG_XFS_RT
|
||||
void xfs_rtbuf_cache_relse(struct xfs_rtalloc_args *args);
|
||||
|
||||
int xfs_rtbuf_get(struct xfs_rtalloc_args *args, xfs_fileoff_t block,
|
||||
int issum);
|
||||
|
||||
static inline int
|
||||
xfs_rtbitmap_read_buf(
|
||||
struct xfs_rtalloc_args *args,
|
||||
xfs_fileoff_t block)
|
||||
{
|
||||
return xfs_rtbuf_get(args, block, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
xfs_rtsummary_read_buf(
|
||||
struct xfs_rtalloc_args *args,
|
||||
xfs_fileoff_t block)
|
||||
{
|
||||
return xfs_rtbuf_get(args, block, 1);
|
||||
}
|
||||
|
||||
int xfs_rtbitmap_read_buf(struct xfs_rtalloc_args *args, xfs_fileoff_t block);
|
||||
int xfs_rtsummary_read_buf(struct xfs_rtalloc_args *args, xfs_fileoff_t block);
|
||||
int xfs_rtcheck_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
|
||||
xfs_rtxlen_t len, int val, xfs_rtxnum_t *new, int *stat);
|
||||
int xfs_rtfind_back(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
|
||||
xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
|
||||
xfs_rtxnum_t *rtblock);
|
||||
int xfs_rtfind_forw(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
|
||||
xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
|
||||
int xfs_rtmodify_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
|
||||
|
|
@ -361,8 +343,12 @@ xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
|
|||
unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
|
||||
unsigned int rsumlevels, xfs_extlen_t rbmblocks);
|
||||
|
||||
void xfs_rtbitmap_lock(struct xfs_trans *tp, struct xfs_mount *mp);
|
||||
int xfs_rtfile_initialize_blocks(struct xfs_inode *ip,
|
||||
xfs_fileoff_t offset_fsb, xfs_fileoff_t end_fsb, void *data);
|
||||
|
||||
void xfs_rtbitmap_lock(struct xfs_mount *mp);
|
||||
void xfs_rtbitmap_unlock(struct xfs_mount *mp);
|
||||
void xfs_rtbitmap_trans_join(struct xfs_trans *tp);
|
||||
|
||||
/* Lock the rt bitmap inode in shared mode */
|
||||
#define XFS_RBMLOCK_BITMAP (1U << 0)
|
||||
|
|
@ -391,7 +377,8 @@ xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
|
|||
# define xfs_rtbitmap_wordcount(mp, r) (0)
|
||||
# define xfs_rtsummary_blockcount(mp, l, b) (0)
|
||||
# define xfs_rtsummary_wordcount(mp, l, b) (0)
|
||||
# define xfs_rtbitmap_lock(tp, mp) do { } while (0)
|
||||
# define xfs_rtbitmap_lock(mp) do { } while (0)
|
||||
# define xfs_rtbitmap_trans_join(tp) do { } while (0)
|
||||
# define xfs_rtbitmap_unlock(mp) do { } while (0)
|
||||
# define xfs_rtbitmap_lock_shared(mp, lf) do { } while (0)
|
||||
# define xfs_rtbitmap_unlock_shared(mp, lf) do { } while (0)
|
||||
|
|
|
|||
|
|
@ -232,6 +232,38 @@ xfs_validate_sb_read(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
xfs_sb_calc_rbmblocks(
|
||||
struct xfs_sb *sbp)
|
||||
{
|
||||
return howmany_64(sbp->sb_rextents, NBBY * sbp->sb_blocksize);
|
||||
}
|
||||
|
||||
/* Validate the realtime geometry */
|
||||
bool
|
||||
xfs_validate_rt_geometry(
|
||||
struct xfs_sb *sbp)
|
||||
{
|
||||
if (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE ||
|
||||
sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)
|
||||
return false;
|
||||
|
||||
if (sbp->sb_rblocks == 0) {
|
||||
if (sbp->sb_rextents != 0 || sbp->sb_rbmblocks != 0 ||
|
||||
sbp->sb_rextslog != 0 || sbp->sb_frextents != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sbp->sb_rextents == 0 ||
|
||||
sbp->sb_rextents != div_u64(sbp->sb_rblocks, sbp->sb_rextsize) ||
|
||||
sbp->sb_rextslog != xfs_compute_rextslog(sbp->sb_rextents) ||
|
||||
sbp->sb_rbmblocks != xfs_sb_calc_rbmblocks(sbp))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check all the superblock fields we care about when writing one out. */
|
||||
STATIC int
|
||||
xfs_validate_sb_write(
|
||||
|
|
@ -491,39 +523,13 @@ xfs_validate_sb_common(
|
|||
}
|
||||
}
|
||||
|
||||
/* Validate the realtime geometry; stolen from xfs_repair */
|
||||
if (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE ||
|
||||
sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) {
|
||||
if (!xfs_validate_rt_geometry(sbp)) {
|
||||
xfs_notice(mp,
|
||||
"realtime extent sanity check failed");
|
||||
"realtime %sgeometry check failed",
|
||||
sbp->sb_rblocks ? "" : "zeroed ");
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (sbp->sb_rblocks == 0) {
|
||||
if (sbp->sb_rextents != 0 || sbp->sb_rbmblocks != 0 ||
|
||||
sbp->sb_rextslog != 0 || sbp->sb_frextents != 0) {
|
||||
xfs_notice(mp,
|
||||
"realtime zeroed geometry check failed");
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
} else {
|
||||
uint64_t rexts;
|
||||
uint64_t rbmblocks;
|
||||
|
||||
rexts = div_u64(sbp->sb_rblocks, sbp->sb_rextsize);
|
||||
rbmblocks = howmany_64(sbp->sb_rextents,
|
||||
NBBY * sbp->sb_blocksize);
|
||||
|
||||
if (!xfs_validate_rtextents(rexts) ||
|
||||
sbp->sb_rextents != rexts ||
|
||||
sbp->sb_rextslog != xfs_compute_rextslog(rexts) ||
|
||||
sbp->sb_rbmblocks != rbmblocks) {
|
||||
xfs_notice(mp,
|
||||
"realtime geometry sanity check failed");
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Either (sb_unit and !hasdalign) or (!sb_unit and hasdalign)
|
||||
* would imply the image is corrupted.
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ extern int xfs_sb_get_secondary(struct xfs_mount *mp,
|
|||
bool xfs_validate_stripe_geometry(struct xfs_mount *mp,
|
||||
__s64 sunit, __s64 swidth, int sectorsize, bool may_repair,
|
||||
bool silent);
|
||||
bool xfs_validate_rt_geometry(struct xfs_sb *sbp);
|
||||
|
||||
uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents);
|
||||
|
||||
|
|
|
|||
|
|
@ -235,16 +235,4 @@ bool xfs_verify_fileoff(struct xfs_mount *mp, xfs_fileoff_t off);
|
|||
bool xfs_verify_fileext(struct xfs_mount *mp, xfs_fileoff_t off,
|
||||
xfs_fileoff_t len);
|
||||
|
||||
/* Do we support an rt volume having this number of rtextents? */
|
||||
static inline bool
|
||||
xfs_validate_rtextents(
|
||||
xfs_rtbxlen_t rtextents)
|
||||
{
|
||||
/* No runt rt volumes */
|
||||
if (rtextents == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __XFS_TYPES_H__ */
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ xfs_rtallocate_range(
|
|||
* We need to find the beginning and end of the extent so we can
|
||||
* properly update the summary.
|
||||
*/
|
||||
error = xfs_rtfind_back(args, start, 0, &preblock);
|
||||
error = xfs_rtfind_back(args, start, &preblock);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
|
@ -259,9 +259,9 @@ xfs_rtallocate_extent_block(
|
|||
/*
|
||||
* i for maxlen is all free, allocate and return that.
|
||||
*/
|
||||
bestlen = maxlen;
|
||||
besti = i;
|
||||
goto allocate;
|
||||
*len = maxlen;
|
||||
*rtx = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -312,12 +312,8 @@ xfs_rtallocate_extent_block(
|
|||
}
|
||||
|
||||
/*
|
||||
* Allocate besti for bestlen & return that.
|
||||
* Pick besti for bestlen & return that.
|
||||
*/
|
||||
allocate:
|
||||
error = xfs_rtallocate_range(args, besti, bestlen);
|
||||
if (error)
|
||||
return error;
|
||||
*len = bestlen;
|
||||
*rtx = besti;
|
||||
return 0;
|
||||
|
|
@ -371,12 +367,6 @@ xfs_rtallocate_extent_exact(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate what we can and return it.
|
||||
*/
|
||||
error = xfs_rtallocate_range(args, start, maxlen);
|
||||
if (error)
|
||||
return error;
|
||||
*len = maxlen;
|
||||
*rtx = start;
|
||||
return 0;
|
||||
|
|
@ -429,7 +419,6 @@ xfs_rtallocate_extent_near(
|
|||
if (error != -ENOSPC)
|
||||
return error;
|
||||
|
||||
|
||||
bbno = xfs_rtx_to_rbmblock(mp, start);
|
||||
i = 0;
|
||||
j = -1;
|
||||
|
|
@ -552,11 +541,11 @@ xfs_rtalloc_sumlevel(
|
|||
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
|
||||
{
|
||||
xfs_fileoff_t i; /* bitmap block number */
|
||||
int error;
|
||||
|
||||
for (i = 0; i < args->mp->m_sb.sb_rbmblocks; i++) {
|
||||
xfs_suminfo_t sum; /* summary information for extents */
|
||||
xfs_rtxnum_t n; /* next rtext to be tried */
|
||||
int error;
|
||||
|
||||
error = xfs_rtget_summary(args, l, i, &sum);
|
||||
if (error)
|
||||
|
|
@ -652,136 +641,20 @@ xfs_rtallocate_extent_size(
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space to the bitmap or summary file, and zero it, for growfs.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_growfs_rt_alloc(
|
||||
struct xfs_mount *mp, /* file system mount point */
|
||||
xfs_extlen_t oblocks, /* old count of blocks */
|
||||
xfs_extlen_t nblocks, /* new count of blocks */
|
||||
struct xfs_inode *ip) /* inode (bitmap/summary) */
|
||||
{
|
||||
xfs_fileoff_t bno; /* block number in file */
|
||||
struct xfs_buf *bp; /* temporary buffer for zeroing */
|
||||
xfs_daddr_t d; /* disk block address */
|
||||
int error; /* error return value */
|
||||
xfs_fsblock_t fsbno; /* filesystem block for bno */
|
||||
struct xfs_bmbt_irec map; /* block map output */
|
||||
int nmap; /* number of block maps */
|
||||
int resblks; /* space reservation */
|
||||
enum xfs_blft buf_type;
|
||||
struct xfs_trans *tp;
|
||||
|
||||
if (ip == mp->m_rsumip)
|
||||
buf_type = XFS_BLFT_RTSUMMARY_BUF;
|
||||
else
|
||||
buf_type = XFS_BLFT_RTBITMAP_BUF;
|
||||
|
||||
/*
|
||||
* Allocate space to the file, as necessary.
|
||||
*/
|
||||
while (oblocks < nblocks) {
|
||||
resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
|
||||
/*
|
||||
* Reserve space & log for one extent added to the file.
|
||||
*/
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc, resblks,
|
||||
0, 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
* Lock the inode.
|
||||
*/
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
|
||||
error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK,
|
||||
XFS_IEXT_ADD_NOSPLIT_CNT);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
|
||||
/*
|
||||
* Allocate blocks to the bitmap file.
|
||||
*/
|
||||
nmap = 1;
|
||||
error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
|
||||
XFS_BMAPI_METADATA, 0, &map, &nmap);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
/*
|
||||
* Free any blocks freed up in the transaction, then commit.
|
||||
*/
|
||||
error = xfs_trans_commit(tp);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
* Now we need to clear the allocated blocks.
|
||||
* Do this one block per transaction, to keep it simple.
|
||||
*/
|
||||
for (bno = map.br_startoff, fsbno = map.br_startblock;
|
||||
bno < map.br_startoff + map.br_blockcount;
|
||||
bno++, fsbno++) {
|
||||
/*
|
||||
* Reserve log for one block zeroing.
|
||||
*/
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero,
|
||||
0, 0, 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
* Lock the bitmap inode.
|
||||
*/
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
/*
|
||||
* Get a buffer for the block.
|
||||
*/
|
||||
d = XFS_FSB_TO_DADDR(mp, fsbno);
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize, 0, &bp);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
|
||||
xfs_trans_buf_set_type(tp, bp, buf_type);
|
||||
bp->b_ops = &xfs_rtbuf_ops;
|
||||
memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
|
||||
xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
|
||||
/*
|
||||
* Commit the transaction.
|
||||
*/
|
||||
error = xfs_trans_commit(tp);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
/*
|
||||
* Go on to the next extent, if any.
|
||||
*/
|
||||
oblocks = map.br_startoff + map.br_blockcount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_trans_cancel:
|
||||
xfs_trans_cancel(tp);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
xfs_alloc_rsum_cache(
|
||||
xfs_mount_t *mp, /* file system mount structure */
|
||||
xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */
|
||||
struct xfs_mount *mp,
|
||||
xfs_extlen_t rbmblocks)
|
||||
{
|
||||
/*
|
||||
* The rsum cache is initialized to the maximum value, which is
|
||||
* trivially an upper bound on the maximum level with any free extents.
|
||||
* We can continue without the cache if it couldn't be allocated.
|
||||
*/
|
||||
mp->m_rsum_cache = kvmalloc(rbmblocks, GFP_KERNEL);
|
||||
if (mp->m_rsum_cache)
|
||||
memset(mp->m_rsum_cache, -1, rbmblocks);
|
||||
else
|
||||
xfs_warn(mp, "could not allocate realtime summary cache");
|
||||
if (!mp->m_rsum_cache)
|
||||
return -ENOMEM;
|
||||
memset(mp->m_rsum_cache, -1, rbmblocks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -817,9 +690,166 @@ xfs_growfs_rt_fixup_extsize(
|
|||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_growfs_rt_bmblock(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rfsblock_t nrblocks,
|
||||
xfs_agblock_t rextsize,
|
||||
xfs_fileoff_t bmbno)
|
||||
{
|
||||
struct xfs_inode *rbmip = mp->m_rbmip;
|
||||
struct xfs_inode *rsumip = mp->m_rsumip;
|
||||
struct xfs_rtalloc_args args = {
|
||||
.mp = mp,
|
||||
};
|
||||
struct xfs_rtalloc_args nargs = {
|
||||
};
|
||||
struct xfs_mount *nmp;
|
||||
xfs_rfsblock_t nrblocks_step;
|
||||
xfs_rtbxlen_t freed_rtx;
|
||||
int error;
|
||||
|
||||
|
||||
nrblocks_step = (bmbno + 1) * NBBY * mp->m_sb.sb_blocksize * rextsize;
|
||||
|
||||
nmp = nargs.mp = kmemdup(mp, sizeof(*mp), GFP_KERNEL);
|
||||
if (!nmp)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Calculate new sb and mount fields for this round.
|
||||
*/
|
||||
nmp->m_rtxblklog = -1; /* don't use shift or masking */
|
||||
nmp->m_sb.sb_rextsize = rextsize;
|
||||
nmp->m_sb.sb_rbmblocks = bmbno + 1;
|
||||
nmp->m_sb.sb_rblocks = min(nrblocks, nrblocks_step);
|
||||
nmp->m_sb.sb_rextents = xfs_rtb_to_rtx(nmp, nmp->m_sb.sb_rblocks);
|
||||
nmp->m_sb.sb_rextslog = xfs_compute_rextslog(nmp->m_sb.sb_rextents);
|
||||
nmp->m_rsumlevels = nmp->m_sb.sb_rextslog + 1;
|
||||
nmp->m_rsumsize = XFS_FSB_TO_B(mp,
|
||||
xfs_rtsummary_blockcount(mp, nmp->m_rsumlevels,
|
||||
nmp->m_sb.sb_rbmblocks));
|
||||
|
||||
/* recompute growfsrt reservation from new rsumsize */
|
||||
xfs_trans_resv_calc(nmp, &nmp->m_resv);
|
||||
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtfree, 0, 0, 0,
|
||||
&args.tp);
|
||||
if (error)
|
||||
goto out_free;
|
||||
nargs.tp = args.tp;
|
||||
|
||||
xfs_rtbitmap_lock(mp);
|
||||
xfs_rtbitmap_trans_join(args.tp);
|
||||
|
||||
/*
|
||||
* Update the bitmap inode's size ondisk and incore. We need to update
|
||||
* the incore size so that inode inactivation won't punch what it thinks
|
||||
* are "posteof" blocks.
|
||||
*/
|
||||
rbmip->i_disk_size = nmp->m_sb.sb_rbmblocks * nmp->m_sb.sb_blocksize;
|
||||
i_size_write(VFS_I(rbmip), rbmip->i_disk_size);
|
||||
xfs_trans_log_inode(args.tp, rbmip, XFS_ILOG_CORE);
|
||||
|
||||
/*
|
||||
* Update the summary inode's size. We need to update the incore size
|
||||
* so that inode inactivation won't punch what it thinks are "posteof"
|
||||
* blocks.
|
||||
*/
|
||||
rsumip->i_disk_size = nmp->m_rsumsize;
|
||||
i_size_write(VFS_I(rsumip), rsumip->i_disk_size);
|
||||
xfs_trans_log_inode(args.tp, rsumip, XFS_ILOG_CORE);
|
||||
|
||||
/*
|
||||
* Copy summary data from old to new sizes when the real size (not
|
||||
* block-aligned) changes.
|
||||
*/
|
||||
if (mp->m_sb.sb_rbmblocks != nmp->m_sb.sb_rbmblocks ||
|
||||
mp->m_rsumlevels != nmp->m_rsumlevels) {
|
||||
error = xfs_rtcopy_summary(&args, &nargs);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update superblock fields.
|
||||
*/
|
||||
if (nmp->m_sb.sb_rextsize != mp->m_sb.sb_rextsize)
|
||||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTSIZE,
|
||||
nmp->m_sb.sb_rextsize - mp->m_sb.sb_rextsize);
|
||||
if (nmp->m_sb.sb_rbmblocks != mp->m_sb.sb_rbmblocks)
|
||||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_RBMBLOCKS,
|
||||
nmp->m_sb.sb_rbmblocks - mp->m_sb.sb_rbmblocks);
|
||||
if (nmp->m_sb.sb_rblocks != mp->m_sb.sb_rblocks)
|
||||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_RBLOCKS,
|
||||
nmp->m_sb.sb_rblocks - mp->m_sb.sb_rblocks);
|
||||
if (nmp->m_sb.sb_rextents != mp->m_sb.sb_rextents)
|
||||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTENTS,
|
||||
nmp->m_sb.sb_rextents - mp->m_sb.sb_rextents);
|
||||
if (nmp->m_sb.sb_rextslog != mp->m_sb.sb_rextslog)
|
||||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTSLOG,
|
||||
nmp->m_sb.sb_rextslog - mp->m_sb.sb_rextslog);
|
||||
|
||||
/*
|
||||
* Free the new extent.
|
||||
*/
|
||||
freed_rtx = nmp->m_sb.sb_rextents - mp->m_sb.sb_rextents;
|
||||
error = xfs_rtfree_range(&nargs, mp->m_sb.sb_rextents, freed_rtx);
|
||||
xfs_rtbuf_cache_relse(&nargs);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
/*
|
||||
* Mark more blocks free in the superblock.
|
||||
*/
|
||||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_FREXTENTS, freed_rtx);
|
||||
|
||||
/*
|
||||
* Update mp values into the real mp structure.
|
||||
*/
|
||||
mp->m_rsumlevels = nmp->m_rsumlevels;
|
||||
mp->m_rsumsize = nmp->m_rsumsize;
|
||||
|
||||
/*
|
||||
* Recompute the growfsrt reservation from the new rsumsize.
|
||||
*/
|
||||
xfs_trans_resv_calc(mp, &mp->m_resv);
|
||||
|
||||
error = xfs_trans_commit(args.tp);
|
||||
if (error)
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
* Ensure the mount RT feature flag is now set.
|
||||
*/
|
||||
mp->m_features |= XFS_FEAT_REALTIME;
|
||||
|
||||
kfree(nmp);
|
||||
return 0;
|
||||
|
||||
out_cancel:
|
||||
xfs_trans_cancel(args.tp);
|
||||
out_free:
|
||||
kfree(nmp);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Visible (exported) functions.
|
||||
* Calculate the last rbmblock currently used.
|
||||
*
|
||||
* This also deals with the case where there were no rtextents before.
|
||||
*/
|
||||
static xfs_fileoff_t
|
||||
xfs_last_rt_bmblock(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
xfs_fileoff_t bmbno = mp->m_sb.sb_rbmblocks;
|
||||
|
||||
/* Skip the current block if it is exactly full. */
|
||||
if (xfs_rtx_to_rbmword(mp, mp->m_sb.sb_rextents) != 0)
|
||||
bmbno--;
|
||||
return bmbno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grow the realtime area of the filesystem.
|
||||
|
|
@ -832,23 +862,14 @@ xfs_growfs_rt(
|
|||
xfs_fileoff_t bmbno; /* bitmap block number */
|
||||
struct xfs_buf *bp; /* temporary buffer */
|
||||
int error; /* error return value */
|
||||
xfs_mount_t *nmp; /* new (fake) mount structure */
|
||||
xfs_rfsblock_t nrblocks; /* new number of realtime blocks */
|
||||
xfs_extlen_t nrbmblocks; /* new number of rt bitmap blocks */
|
||||
xfs_rtxnum_t nrextents; /* new number of realtime extents */
|
||||
uint8_t nrextslog; /* new log2 of sb_rextents */
|
||||
xfs_extlen_t nrsumblocks; /* new number of summary blocks */
|
||||
uint nrsumlevels; /* new rt summary levels */
|
||||
uint nrsumsize; /* new size of rt summary, bytes */
|
||||
xfs_sb_t *nsbp; /* new superblock */
|
||||
xfs_extlen_t rbmblocks; /* current number of rt bitmap blocks */
|
||||
xfs_extlen_t rsumblocks; /* current number of rt summary blks */
|
||||
xfs_sb_t *sbp; /* old superblock */
|
||||
uint8_t *rsum_cache; /* old summary cache */
|
||||
xfs_agblock_t old_rextsize = mp->m_sb.sb_rextsize;
|
||||
|
||||
sbp = &mp->m_sb;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
|
|
@ -867,11 +888,10 @@ xfs_growfs_rt(
|
|||
goto out_unlock;
|
||||
|
||||
/* Shrink not supported. */
|
||||
if (in->newblocks <= sbp->sb_rblocks)
|
||||
if (in->newblocks <= mp->m_sb.sb_rblocks)
|
||||
goto out_unlock;
|
||||
|
||||
/* Can only change rt extent size when adding rt volume. */
|
||||
if (sbp->sb_rblocks > 0 && in->extsize != sbp->sb_rextsize)
|
||||
if (mp->m_sb.sb_rblocks > 0 && in->extsize != mp->m_sb.sb_rextsize)
|
||||
goto out_unlock;
|
||||
|
||||
/* Range check the extent size. */
|
||||
|
|
@ -884,15 +904,14 @@ xfs_growfs_rt(
|
|||
if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp) || xfs_has_quota(mp))
|
||||
goto out_unlock;
|
||||
|
||||
nrblocks = in->newblocks;
|
||||
error = xfs_sb_validate_fsb_count(sbp, nrblocks);
|
||||
error = xfs_sb_validate_fsb_count(&mp->m_sb, in->newblocks);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
/*
|
||||
* Read in the last block of the device, make sure it exists.
|
||||
*/
|
||||
error = xfs_buf_read_uncached(mp->m_rtdev_targp,
|
||||
XFS_FSB_TO_BB(mp, nrblocks - 1),
|
||||
XFS_FSB_TO_BB(mp, in->newblocks - 1),
|
||||
XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
|
@ -901,17 +920,15 @@ xfs_growfs_rt(
|
|||
/*
|
||||
* Calculate new parameters. These are the final values to be reached.
|
||||
*/
|
||||
nrextents = nrblocks;
|
||||
do_div(nrextents, in->extsize);
|
||||
if (!xfs_validate_rtextents(nrextents)) {
|
||||
nrextents = div_u64(in->newblocks, in->extsize);
|
||||
if (nrextents == 0) {
|
||||
error = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents);
|
||||
nrextslog = xfs_compute_rextslog(nrextents);
|
||||
nrsumlevels = nrextslog + 1;
|
||||
nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels, nrbmblocks);
|
||||
nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
|
||||
nrsumblocks = xfs_rtsummary_blockcount(mp,
|
||||
xfs_compute_rextslog(nrextents) + 1, nrbmblocks);
|
||||
|
||||
/*
|
||||
* New summary size can't be more than half the size of
|
||||
* the log. This prevents us from getting a log overflow,
|
||||
|
|
@ -931,154 +948,29 @@ xfs_growfs_rt(
|
|||
/*
|
||||
* Allocate space to the bitmap and summary files, as necessary.
|
||||
*/
|
||||
error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
|
||||
error = xfs_rtfile_initialize_blocks(mp->m_rbmip, rbmblocks,
|
||||
nrbmblocks, NULL);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
|
||||
error = xfs_rtfile_initialize_blocks(mp->m_rsumip, rsumblocks,
|
||||
nrsumblocks, NULL);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
rsum_cache = mp->m_rsum_cache;
|
||||
if (nrbmblocks != sbp->sb_rbmblocks)
|
||||
xfs_alloc_rsum_cache(mp, nrbmblocks);
|
||||
|
||||
/*
|
||||
* Allocate a new (fake) mount/sb.
|
||||
*/
|
||||
nmp = kmalloc(sizeof(*nmp), GFP_KERNEL | __GFP_NOFAIL);
|
||||
/*
|
||||
* Loop over the bitmap blocks.
|
||||
* We will do everything one bitmap block at a time.
|
||||
* Skip the current block if it is exactly full.
|
||||
* This also deals with the case where there were no rtextents before.
|
||||
*/
|
||||
for (bmbno = sbp->sb_rbmblocks -
|
||||
((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
|
||||
bmbno < nrbmblocks;
|
||||
bmbno++) {
|
||||
struct xfs_rtalloc_args args = {
|
||||
.mp = mp,
|
||||
};
|
||||
struct xfs_rtalloc_args nargs = {
|
||||
.mp = nmp,
|
||||
};
|
||||
struct xfs_trans *tp;
|
||||
xfs_rfsblock_t nrblocks_step;
|
||||
|
||||
*nmp = *mp;
|
||||
nsbp = &nmp->m_sb;
|
||||
/*
|
||||
* Calculate new sb and mount fields for this round.
|
||||
*/
|
||||
nsbp->sb_rextsize = in->extsize;
|
||||
nmp->m_rtxblklog = -1; /* don't use shift or masking */
|
||||
nsbp->sb_rbmblocks = bmbno + 1;
|
||||
nrblocks_step = (bmbno + 1) * NBBY * nsbp->sb_blocksize *
|
||||
nsbp->sb_rextsize;
|
||||
nsbp->sb_rblocks = min(nrblocks, nrblocks_step);
|
||||
nsbp->sb_rextents = xfs_rtb_to_rtx(nmp, nsbp->sb_rblocks);
|
||||
ASSERT(nsbp->sb_rextents != 0);
|
||||
nsbp->sb_rextslog = xfs_compute_rextslog(nsbp->sb_rextents);
|
||||
nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
|
||||
nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels,
|
||||
nsbp->sb_rbmblocks);
|
||||
nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
|
||||
/* recompute growfsrt reservation from new rsumsize */
|
||||
xfs_trans_resv_calc(nmp, &nmp->m_resv);
|
||||
|
||||
/*
|
||||
* Start a transaction, get the log reservation.
|
||||
*/
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtfree, 0, 0, 0,
|
||||
&tp);
|
||||
if (nrbmblocks != mp->m_sb.sb_rbmblocks) {
|
||||
error = xfs_alloc_rsum_cache(mp, nrbmblocks);
|
||||
if (error)
|
||||
break;
|
||||
args.tp = tp;
|
||||
nargs.tp = tp;
|
||||
|
||||
/*
|
||||
* Lock out other callers by grabbing the bitmap and summary
|
||||
* inode locks and joining them to the transaction.
|
||||
*/
|
||||
xfs_rtbitmap_lock(tp, mp);
|
||||
/*
|
||||
* Update the bitmap inode's size ondisk and incore. We need
|
||||
* to update the incore size so that inode inactivation won't
|
||||
* punch what it thinks are "posteof" blocks.
|
||||
*/
|
||||
mp->m_rbmip->i_disk_size =
|
||||
nsbp->sb_rbmblocks * nsbp->sb_blocksize;
|
||||
i_size_write(VFS_I(mp->m_rbmip), mp->m_rbmip->i_disk_size);
|
||||
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
|
||||
/*
|
||||
* Update the summary inode's size. We need to update the
|
||||
* incore size so that inode inactivation won't punch what it
|
||||
* thinks are "posteof" blocks.
|
||||
*/
|
||||
mp->m_rsumip->i_disk_size = nmp->m_rsumsize;
|
||||
i_size_write(VFS_I(mp->m_rsumip), mp->m_rsumip->i_disk_size);
|
||||
xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
|
||||
/*
|
||||
* Copy summary data from old to new sizes.
|
||||
* Do this when the real size (not block-aligned) changes.
|
||||
*/
|
||||
if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
|
||||
mp->m_rsumlevels != nmp->m_rsumlevels) {
|
||||
error = xfs_rtcopy_summary(&args, &nargs);
|
||||
if (error)
|
||||
goto error_cancel;
|
||||
}
|
||||
/*
|
||||
* Update superblock fields.
|
||||
*/
|
||||
if (nsbp->sb_rextsize != sbp->sb_rextsize)
|
||||
xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
|
||||
nsbp->sb_rextsize - sbp->sb_rextsize);
|
||||
if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
|
||||
xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
|
||||
nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
|
||||
if (nsbp->sb_rblocks != sbp->sb_rblocks)
|
||||
xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
|
||||
nsbp->sb_rblocks - sbp->sb_rblocks);
|
||||
if (nsbp->sb_rextents != sbp->sb_rextents)
|
||||
xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
|
||||
nsbp->sb_rextents - sbp->sb_rextents);
|
||||
if (nsbp->sb_rextslog != sbp->sb_rextslog)
|
||||
xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
|
||||
nsbp->sb_rextslog - sbp->sb_rextslog);
|
||||
/*
|
||||
* Free new extent.
|
||||
*/
|
||||
error = xfs_rtfree_range(&nargs, sbp->sb_rextents,
|
||||
nsbp->sb_rextents - sbp->sb_rextents);
|
||||
xfs_rtbuf_cache_relse(&nargs);
|
||||
if (error) {
|
||||
error_cancel:
|
||||
xfs_trans_cancel(tp);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Mark more blocks free in the superblock.
|
||||
*/
|
||||
xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
|
||||
nsbp->sb_rextents - sbp->sb_rextents);
|
||||
/*
|
||||
* Update mp values into the real mp structure.
|
||||
*/
|
||||
mp->m_rsumlevels = nrsumlevels;
|
||||
mp->m_rsumsize = nrsumsize;
|
||||
/* recompute growfsrt reservation from new rsumsize */
|
||||
xfs_trans_resv_calc(mp, &mp->m_resv);
|
||||
|
||||
error = xfs_trans_commit(tp);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
/* Ensure the mount RT feature flag is now set. */
|
||||
mp->m_features |= XFS_FEAT_REALTIME;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* Initialize the free space bitmap one bitmap block at a time. */
|
||||
for (bmbno = xfs_last_rt_bmblock(mp); bmbno < nrbmblocks; bmbno++) {
|
||||
error = xfs_growfs_rt_bmblock(mp, in->newblocks, in->extsize,
|
||||
bmbno);
|
||||
if (error)
|
||||
goto out_free;
|
||||
}
|
||||
if (error)
|
||||
goto out_free;
|
||||
|
||||
if (old_rextsize != in->extsize) {
|
||||
error = xfs_growfs_rt_fixup_extsize(mp);
|
||||
|
|
@ -1090,11 +982,6 @@ xfs_growfs_rt(
|
|||
error = xfs_update_secondary_sbs(mp);
|
||||
|
||||
out_free:
|
||||
/*
|
||||
* Free the fake mp structure.
|
||||
*/
|
||||
kfree(nmp);
|
||||
|
||||
/*
|
||||
* If we had to allocate a new rsum_cache, we either need to free the
|
||||
* old one (if we succeeded) or free the new one and restore the old one
|
||||
|
|
@ -1268,7 +1155,9 @@ xfs_rtmount_inodes(
|
|||
if (error)
|
||||
goto out_rele_summary;
|
||||
|
||||
xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
|
||||
error = xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
|
||||
if (error)
|
||||
goto out_rele_summary;
|
||||
return 0;
|
||||
|
||||
out_rele_summary:
|
||||
|
|
@ -1296,12 +1185,11 @@ xfs_rtunmount_inodes(
|
|||
* of rtextents and the fraction.
|
||||
* The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
|
||||
*/
|
||||
static int
|
||||
static xfs_rtxnum_t
|
||||
xfs_rtpick_extent(
|
||||
xfs_mount_t *mp, /* file system mount point */
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_rtxlen_t len, /* allocation length (rtextents) */
|
||||
xfs_rtxnum_t *pick) /* result rt extent */
|
||||
xfs_rtxlen_t len) /* allocation length (rtextents) */
|
||||
{
|
||||
xfs_rtxnum_t b; /* result rtext */
|
||||
int log2; /* log of sequence number */
|
||||
|
|
@ -1332,8 +1220,7 @@ xfs_rtpick_extent(
|
|||
ts.tv_sec = seq + 1;
|
||||
inode_set_atime_to_ts(VFS_I(mp->m_rbmip), ts);
|
||||
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
|
||||
*pick = b;
|
||||
return 0;
|
||||
return b;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1427,7 +1314,8 @@ xfs_bmap_rtalloc(
|
|||
* Lock out modifications to both the RT bitmap and summary inodes
|
||||
*/
|
||||
if (!rtlocked) {
|
||||
xfs_rtbitmap_lock(ap->tp, mp);
|
||||
xfs_rtbitmap_lock(mp);
|
||||
xfs_rtbitmap_trans_join(ap->tp);
|
||||
rtlocked = true;
|
||||
}
|
||||
|
||||
|
|
@ -1440,9 +1328,7 @@ xfs_bmap_rtalloc(
|
|||
* If it's an allocation to an empty file at offset 0, pick an
|
||||
* extent that will space things out in the rt area.
|
||||
*/
|
||||
error = xfs_rtpick_extent(mp, ap->tp, ralen, &start);
|
||||
if (error)
|
||||
return error;
|
||||
start = xfs_rtpick_extent(mp, ap->tp, ralen);
|
||||
} else {
|
||||
start = 0;
|
||||
}
|
||||
|
|
@ -1467,9 +1353,12 @@ xfs_bmap_rtalloc(
|
|||
error = xfs_rtallocate_extent_size(&args, raminlen,
|
||||
ralen, &ralen, prod, &rtx);
|
||||
}
|
||||
xfs_rtbuf_cache_relse(&args);
|
||||
|
||||
if (error == -ENOSPC) {
|
||||
if (error) {
|
||||
xfs_rtbuf_cache_relse(&args);
|
||||
if (error != -ENOSPC)
|
||||
return error;
|
||||
|
||||
if (align > mp->m_sb.sb_rextsize) {
|
||||
/*
|
||||
* We previously enlarged the request length to try to
|
||||
|
|
@ -1497,14 +1386,20 @@ xfs_bmap_rtalloc(
|
|||
ap->length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = xfs_rtallocate_range(&args, rtx, ralen);
|
||||
if (error)
|
||||
return error;
|
||||
goto out_release;
|
||||
|
||||
xfs_trans_mod_sb(ap->tp, ap->wasdel ?
|
||||
XFS_TRANS_SB_RES_FREXTENTS : XFS_TRANS_SB_FREXTENTS,
|
||||
-(long)ralen);
|
||||
|
||||
ap->blkno = xfs_rtx_to_rtb(mp, rtx);
|
||||
ap->length = xfs_rtxlen_to_extlen(mp, ralen);
|
||||
xfs_bmap_alloc_account(ap);
|
||||
return 0;
|
||||
|
||||
out_release:
|
||||
xfs_rtbuf_cache_relse(&args);
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user