mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
New code for 6.7:
* Realtime device subsystem - Cleanup usage of xfs_rtblock_t and xfs_fsblock_t data types. - Replace open coded conversions between rt blocks and rt extents with calls to static inline helpers. - Replace open coded realtime geometry compuation and macros with helper functions. - CPU usage optimizations for realtime allocator. - Misc. Bug fixes associated with Realtime device. * Allow read operations to execute while an FICLONE ioctl is being serviced. * Misc. bug fixes - Alert user when xfs_droplink() encounters an inode with a link count of zero. - Handle the case where the allocator could return zero extents when servicing an fallocate request. Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQjMC4mbgVeU7MxEIYH7y4RirJu9AUCZUEvIgAKCRAH7y4RirJu 9JnQAQCtnQAhZHbh9U2BNJI4hrpNm4Mh54DVlZvPFHW1N96AUAEA0Hnic/Zusrfc 9aaHQbzs4qGSZ5UJWOU6GxcWob/tggs= =Ay05 -----END PGP SIGNATURE----- Merge tag 'xfs-6.7-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull xfs updates from Chandan Babu: - Realtime device subsystem: - Cleanup usage of xfs_rtblock_t and xfs_fsblock_t data types - Replace open coded conversions between rt blocks and rt extents with calls to static inline helpers - Replace open coded realtime geometry compuation and macros with helper functions - CPU usage optimizations for realtime allocator - Misc bug fixes associated with Realtime device - Allow read operations to execute while an FICLONE ioctl is being serviced - Misc bug fixes: - Alert user when xfs_droplink() encounters an inode with a link count of zero - Handle the case where the allocator could return zero extents when servicing an fallocate request * tag 'xfs-6.7-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (40 commits) xfs: allow read IO and FICLONE to run concurrently xfs: handle nimaps=0 from xfs_bmapi_write in xfs_alloc_file_space xfs: introduce protection for drop nlink xfs: don't look for end of extent further than necessary in xfs_rtallocate_extent_near() xfs: don't try redundant allocations in xfs_rtallocate_extent_near() xfs: limit maxlen based on available space in xfs_rtallocate_extent_near() xfs: return maximum free size from xfs_rtany_summary() xfs: invert the realtime summary cache xfs: simplify rt bitmap/summary block accessor functions xfs: simplify xfs_rtbuf_get calling conventions xfs: cache last bitmap block in realtime allocator xfs: use accessor functions for summary info words xfs: consolidate realtime allocation arguments xfs: create helpers for rtsummary block/wordcount computations xfs: use accessor functions for bitmap words xfs: create helpers for rtbitmap block/wordcount computations xfs: create a helper to handle logging parts of rt bitmap/summary blocks xfs: convert rt summary macros to helpers xfs: convert open-coded xfs_rtword_t pointer accesses to helper xfs: remove XFS_BLOCKWSIZE and XFS_BLOCKWMASK macros ...
This commit is contained in:
commit
34f7632627
@ -21,7 +21,7 @@
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_bmap_util.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "xfs_errortag.h"
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_quota.h"
|
||||
@ -2989,7 +2989,7 @@ xfs_bmap_extsize_align(
|
||||
* If realtime, and the result isn't a multiple of the realtime
|
||||
* extent size we need to remove blocks until it is.
|
||||
*/
|
||||
if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
|
||||
if (rt && (temp = xfs_extlen_to_rtxmod(mp, align_alen))) {
|
||||
/*
|
||||
* We're not covering the original request, or
|
||||
* we won't be able to once we fix the length.
|
||||
@ -3016,7 +3016,7 @@ xfs_bmap_extsize_align(
|
||||
else {
|
||||
align_alen -= orig_off - align_off;
|
||||
align_off = orig_off;
|
||||
align_alen -= align_alen % mp->m_sb.sb_rextsize;
|
||||
align_alen -= xfs_extlen_to_rtxmod(mp, align_alen);
|
||||
}
|
||||
/*
|
||||
* Result doesn't cover the request, fail it.
|
||||
@ -4826,12 +4826,8 @@ xfs_bmap_del_extent_delay(
|
||||
ASSERT(got->br_startoff <= del->br_startoff);
|
||||
ASSERT(got_endoff >= del_endoff);
|
||||
|
||||
if (isrt) {
|
||||
uint64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount);
|
||||
|
||||
do_div(rtexts, mp->m_sb.sb_rextsize);
|
||||
xfs_mod_frextents(mp, rtexts);
|
||||
}
|
||||
if (isrt)
|
||||
xfs_mod_frextents(mp, xfs_rtb_to_rtx(mp, del->br_blockcount));
|
||||
|
||||
/*
|
||||
* Update the inode delalloc counter now and wait to update the
|
||||
@ -5057,33 +5053,20 @@ xfs_bmap_del_extent_real(
|
||||
|
||||
flags = XFS_ILOG_CORE;
|
||||
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
|
||||
xfs_filblks_t len;
|
||||
xfs_extlen_t mod;
|
||||
|
||||
len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
|
||||
&mod);
|
||||
ASSERT(mod == 0);
|
||||
|
||||
if (!(bflags & XFS_BMAPI_REMAP)) {
|
||||
xfs_fsblock_t bno;
|
||||
|
||||
bno = div_u64_rem(del->br_startblock,
|
||||
mp->m_sb.sb_rextsize, &mod);
|
||||
ASSERT(mod == 0);
|
||||
|
||||
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
|
||||
error = xfs_rtfree_blocks(tp, del->br_startblock,
|
||||
del->br_blockcount);
|
||||
if (error)
|
||||
goto done;
|
||||
}
|
||||
|
||||
do_fx = 0;
|
||||
nblks = len * mp->m_sb.sb_rextsize;
|
||||
qfield = XFS_TRANS_DQ_RTBCOUNT;
|
||||
} else {
|
||||
do_fx = 1;
|
||||
nblks = del->br_blockcount;
|
||||
qfield = XFS_TRANS_DQ_BCOUNT;
|
||||
}
|
||||
nblks = del->br_blockcount;
|
||||
|
||||
del_endblock = del->br_startblock + del->br_blockcount;
|
||||
if (cur) {
|
||||
@ -5289,7 +5272,6 @@ __xfs_bunmapi(
|
||||
int tmp_logflags; /* partial logging flags */
|
||||
int wasdel; /* was a delayed alloc extent */
|
||||
int whichfork; /* data or attribute fork */
|
||||
xfs_fsblock_t sum;
|
||||
xfs_filblks_t len = *rlen; /* length to unmap in file */
|
||||
xfs_fileoff_t end;
|
||||
struct xfs_iext_cursor icur;
|
||||
@ -5384,8 +5366,8 @@ __xfs_bunmapi(
|
||||
if (!isrt)
|
||||
goto delete;
|
||||
|
||||
sum = del.br_startblock + del.br_blockcount;
|
||||
div_u64_rem(sum, mp->m_sb.sb_rextsize, &mod);
|
||||
mod = xfs_rtb_to_rtxoff(mp,
|
||||
del.br_startblock + del.br_blockcount);
|
||||
if (mod) {
|
||||
/*
|
||||
* Realtime extent not lined up at the end.
|
||||
@ -5432,7 +5414,8 @@ __xfs_bunmapi(
|
||||
goto error0;
|
||||
goto nodelete;
|
||||
}
|
||||
div_u64_rem(del.br_startblock, mp->m_sb.sb_rextsize, &mod);
|
||||
|
||||
mod = xfs_rtb_to_rtxoff(mp, del.br_startblock);
|
||||
if (mod) {
|
||||
xfs_extlen_t off = mp->m_sb.sb_rextsize - mod;
|
||||
|
||||
@ -6209,8 +6192,8 @@ xfs_bmap_validate_extent(
|
||||
return __this_address;
|
||||
|
||||
if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
|
||||
if (!xfs_verify_rtext(mp, irec->br_startblock,
|
||||
irec->br_blockcount))
|
||||
if (!xfs_verify_rtbext(mp, irec->br_startblock,
|
||||
irec->br_blockcount))
|
||||
return __this_address;
|
||||
} else {
|
||||
if (!xfs_verify_fsbext(mp, irec->br_startblock,
|
||||
|
@ -98,7 +98,7 @@ typedef struct xfs_sb {
|
||||
uint32_t sb_blocksize; /* logical block size, bytes */
|
||||
xfs_rfsblock_t sb_dblocks; /* number of data blocks */
|
||||
xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */
|
||||
xfs_rtblock_t sb_rextents; /* number of realtime extents */
|
||||
xfs_rtbxlen_t sb_rextents; /* number of realtime extents */
|
||||
uuid_t sb_uuid; /* user-visible file system unique id */
|
||||
xfs_fsblock_t sb_logstart; /* starting block of log if internal */
|
||||
xfs_ino_t sb_rootino; /* root inode number */
|
||||
@ -690,6 +690,22 @@ struct xfs_agfl {
|
||||
ASSERT(xfs_daddr_to_agno(mp, d) == \
|
||||
xfs_daddr_to_agno(mp, (d) + (len) - 1)))
|
||||
|
||||
/*
|
||||
* Realtime bitmap information is accessed by the word, which is currently
|
||||
* stored in host-endian format.
|
||||
*/
|
||||
union xfs_rtword_raw {
|
||||
__u32 old;
|
||||
};
|
||||
|
||||
/*
|
||||
* Realtime summary counts are accessed by the word, which is currently
|
||||
* stored in host-endian format.
|
||||
*/
|
||||
union xfs_suminfo_raw {
|
||||
__u32 old;
|
||||
};
|
||||
|
||||
/*
|
||||
* XFS Timestamps
|
||||
* ==============
|
||||
@ -1142,24 +1158,10 @@ static inline bool xfs_dinode_has_large_extent_counts(
|
||||
|
||||
#define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize)
|
||||
#define XFS_BLOCKMASK(mp) ((mp)->m_blockmask)
|
||||
#define XFS_BLOCKWSIZE(mp) ((mp)->m_blockwsize)
|
||||
#define XFS_BLOCKWMASK(mp) ((mp)->m_blockwmask)
|
||||
|
||||
/*
|
||||
* RT Summary and bit manipulation macros.
|
||||
* RT bit manipulation macros.
|
||||
*/
|
||||
#define XFS_SUMOFFS(mp,ls,bb) ((int)((ls) * (mp)->m_sb.sb_rbmblocks + (bb)))
|
||||
#define XFS_SUMOFFSTOBLOCK(mp,s) \
|
||||
(((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog)
|
||||
#define XFS_SUMPTR(mp,bp,so) \
|
||||
((xfs_suminfo_t *)((bp)->b_addr + \
|
||||
(((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp))))
|
||||
|
||||
#define XFS_BITTOBLOCK(mp,bi) ((bi) >> (mp)->m_blkbit_log)
|
||||
#define XFS_BLOCKTOBIT(mp,bb) ((bb) << (mp)->m_blkbit_log)
|
||||
#define XFS_BITTOWORD(mp,bi) \
|
||||
((int)(((bi) >> XFS_NBWORDLOG) & XFS_BLOCKWMASK(mp)))
|
||||
|
||||
#define XFS_RTMIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
383
fs/xfs/libxfs/xfs_rtbitmap.h
Normal file
383
fs/xfs/libxfs/xfs_rtbitmap.h
Normal file
@ -0,0 +1,383 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
#ifndef __XFS_RTBITMAP_H__
|
||||
#define __XFS_RTBITMAP_H__
|
||||
|
||||
struct xfs_rtalloc_args {
|
||||
struct xfs_mount *mp;
|
||||
struct xfs_trans *tp;
|
||||
|
||||
struct xfs_buf *rbmbp; /* bitmap block buffer */
|
||||
struct xfs_buf *sumbp; /* summary block buffer */
|
||||
|
||||
xfs_fileoff_t rbmoff; /* bitmap block number */
|
||||
xfs_fileoff_t sumoff; /* summary block number */
|
||||
};
|
||||
|
||||
static inline xfs_rtblock_t
|
||||
xfs_rtx_to_rtb(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtxnum_t rtx)
|
||||
{
|
||||
if (mp->m_rtxblklog >= 0)
|
||||
return rtx << mp->m_rtxblklog;
|
||||
|
||||
return rtx * mp->m_sb.sb_rextsize;
|
||||
}
|
||||
|
||||
static inline xfs_extlen_t
|
||||
xfs_rtxlen_to_extlen(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtxlen_t rtxlen)
|
||||
{
|
||||
if (mp->m_rtxblklog >= 0)
|
||||
return rtxlen << mp->m_rtxblklog;
|
||||
|
||||
return rtxlen * mp->m_sb.sb_rextsize;
|
||||
}
|
||||
|
||||
/* Compute the misalignment between an extent length and a realtime extent .*/
|
||||
static inline unsigned int
|
||||
xfs_extlen_to_rtxmod(
|
||||
struct xfs_mount *mp,
|
||||
xfs_extlen_t len)
|
||||
{
|
||||
if (mp->m_rtxblklog >= 0)
|
||||
return len & mp->m_rtxblkmask;
|
||||
|
||||
return len % mp->m_sb.sb_rextsize;
|
||||
}
|
||||
|
||||
static inline xfs_rtxlen_t
|
||||
xfs_extlen_to_rtxlen(
|
||||
struct xfs_mount *mp,
|
||||
xfs_extlen_t len)
|
||||
{
|
||||
if (mp->m_rtxblklog >= 0)
|
||||
return len >> mp->m_rtxblklog;
|
||||
|
||||
return len / mp->m_sb.sb_rextsize;
|
||||
}
|
||||
|
||||
/* Convert an rt block number into an rt extent number. */
|
||||
static inline xfs_rtxnum_t
|
||||
xfs_rtb_to_rtx(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno)
|
||||
{
|
||||
if (likely(mp->m_rtxblklog >= 0))
|
||||
return rtbno >> mp->m_rtxblklog;
|
||||
|
||||
return div_u64(rtbno, mp->m_sb.sb_rextsize);
|
||||
}
|
||||
|
||||
/* Return the offset of an rt block number within an rt extent. */
|
||||
static inline xfs_extlen_t
|
||||
xfs_rtb_to_rtxoff(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno)
|
||||
{
|
||||
if (likely(mp->m_rtxblklog >= 0))
|
||||
return rtbno & mp->m_rtxblkmask;
|
||||
|
||||
return do_div(rtbno, mp->m_sb.sb_rextsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Crack an rt block number into an rt extent number and an offset within that
|
||||
* rt extent. Returns the rt extent number directly and the offset in @off.
|
||||
*/
|
||||
static inline xfs_rtxnum_t
|
||||
xfs_rtb_to_rtxrem(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno,
|
||||
xfs_extlen_t *off)
|
||||
{
|
||||
if (likely(mp->m_rtxblklog >= 0)) {
|
||||
*off = rtbno & mp->m_rtxblkmask;
|
||||
return rtbno >> mp->m_rtxblklog;
|
||||
}
|
||||
|
||||
return div_u64_rem(rtbno, mp->m_sb.sb_rextsize, off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an rt block number into an rt extent number, rounding up to the next
|
||||
* rt extent if the rt block is not aligned to an rt extent boundary.
|
||||
*/
|
||||
static inline xfs_rtxnum_t
|
||||
xfs_rtb_to_rtxup(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno)
|
||||
{
|
||||
if (likely(mp->m_rtxblklog >= 0)) {
|
||||
if (rtbno & mp->m_rtxblkmask)
|
||||
return (rtbno >> mp->m_rtxblklog) + 1;
|
||||
return rtbno >> mp->m_rtxblklog;
|
||||
}
|
||||
|
||||
if (do_div(rtbno, mp->m_sb.sb_rextsize))
|
||||
rtbno++;
|
||||
return rtbno;
|
||||
}
|
||||
|
||||
/* Round this rtblock up to the nearest rt extent size. */
|
||||
static inline xfs_rtblock_t
|
||||
xfs_rtb_roundup_rtx(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno)
|
||||
{
|
||||
return roundup_64(rtbno, mp->m_sb.sb_rextsize);
|
||||
}
|
||||
|
||||
/* Round this rtblock down to the nearest rt extent size. */
|
||||
static inline xfs_rtblock_t
|
||||
xfs_rtb_rounddown_rtx(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno)
|
||||
{
|
||||
return rounddown_64(rtbno, mp->m_sb.sb_rextsize);
|
||||
}
|
||||
|
||||
/* Convert an rt extent number to a file block offset in the rt bitmap file. */
|
||||
static inline xfs_fileoff_t
|
||||
xfs_rtx_to_rbmblock(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtxnum_t rtx)
|
||||
{
|
||||
return rtx >> mp->m_blkbit_log;
|
||||
}
|
||||
|
||||
/* Convert an rt extent number to a word offset within an rt bitmap block. */
|
||||
static inline unsigned int
|
||||
xfs_rtx_to_rbmword(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtxnum_t rtx)
|
||||
{
|
||||
return (rtx >> XFS_NBWORDLOG) & (mp->m_blockwsize - 1);
|
||||
}
|
||||
|
||||
/* Convert a file block offset in the rt bitmap file to an rt extent number. */
|
||||
static inline xfs_rtxnum_t
|
||||
xfs_rbmblock_to_rtx(
|
||||
struct xfs_mount *mp,
|
||||
xfs_fileoff_t rbmoff)
|
||||
{
|
||||
return rbmoff << mp->m_blkbit_log;
|
||||
}
|
||||
|
||||
/* Return a pointer to a bitmap word within a rt bitmap block. */
|
||||
static inline union xfs_rtword_raw *
|
||||
xfs_rbmblock_wordptr(
|
||||
struct xfs_rtalloc_args *args,
|
||||
unsigned int index)
|
||||
{
|
||||
union xfs_rtword_raw *words = args->rbmbp->b_addr;
|
||||
|
||||
return words + index;
|
||||
}
|
||||
|
||||
/* Convert an ondisk bitmap word to its incore representation. */
|
||||
static inline xfs_rtword_t
|
||||
xfs_rtbitmap_getword(
|
||||
struct xfs_rtalloc_args *args,
|
||||
unsigned int index)
|
||||
{
|
||||
union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
|
||||
|
||||
return word->old;
|
||||
}
|
||||
|
||||
/* Set an ondisk bitmap word from an incore representation. */
|
||||
static inline void
|
||||
xfs_rtbitmap_setword(
|
||||
struct xfs_rtalloc_args *args,
|
||||
unsigned int index,
|
||||
xfs_rtword_t value)
|
||||
{
|
||||
union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
|
||||
|
||||
word->old = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a rt extent length and rt bitmap block number to a xfs_suminfo_t
|
||||
* offset within the rt summary file.
|
||||
*/
|
||||
static inline xfs_rtsumoff_t
|
||||
xfs_rtsumoffs(
|
||||
struct xfs_mount *mp,
|
||||
int log2_len,
|
||||
xfs_fileoff_t rbmoff)
|
||||
{
|
||||
return log2_len * mp->m_sb.sb_rbmblocks + rbmoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an xfs_suminfo_t offset to a file block offset within the rt summary
|
||||
* file.
|
||||
*/
|
||||
static inline xfs_fileoff_t
|
||||
xfs_rtsumoffs_to_block(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtsumoff_t rsumoff)
|
||||
{
|
||||
return XFS_B_TO_FSBT(mp, rsumoff * sizeof(xfs_suminfo_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an xfs_suminfo_t offset to an info word offset within an rt summary
|
||||
* block.
|
||||
*/
|
||||
static inline unsigned int
|
||||
xfs_rtsumoffs_to_infoword(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtsumoff_t rsumoff)
|
||||
{
|
||||
unsigned int mask = mp->m_blockmask >> XFS_SUMINFOLOG;
|
||||
|
||||
return rsumoff & mask;
|
||||
}
|
||||
|
||||
/* Return a pointer to a summary info word within a rt summary block. */
|
||||
static inline union xfs_suminfo_raw *
|
||||
xfs_rsumblock_infoptr(
|
||||
struct xfs_rtalloc_args *args,
|
||||
unsigned int index)
|
||||
{
|
||||
union xfs_suminfo_raw *info = args->sumbp->b_addr;
|
||||
|
||||
return info + index;
|
||||
}
|
||||
|
||||
/* Get the current value of a summary counter. */
|
||||
static inline xfs_suminfo_t
|
||||
xfs_suminfo_get(
|
||||
struct xfs_rtalloc_args *args,
|
||||
unsigned int index)
|
||||
{
|
||||
union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
|
||||
|
||||
return info->old;
|
||||
}
|
||||
|
||||
/* Add to the current value of a summary counter and return the new value. */
|
||||
static inline xfs_suminfo_t
|
||||
xfs_suminfo_add(
|
||||
struct xfs_rtalloc_args *args,
|
||||
unsigned int index,
|
||||
int delta)
|
||||
{
|
||||
union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
|
||||
|
||||
info->old += delta;
|
||||
return info->old;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for walking free space rtextents in the realtime bitmap.
|
||||
*/
|
||||
struct xfs_rtalloc_rec {
|
||||
xfs_rtxnum_t ar_startext;
|
||||
xfs_rtbxlen_t ar_extcount;
|
||||
};
|
||||
|
||||
typedef int (*xfs_rtalloc_query_range_fn)(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
const struct xfs_rtalloc_rec *rec,
|
||||
void *priv);
|
||||
|
||||
#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_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);
|
||||
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,
|
||||
xfs_rtxlen_t len, int val);
|
||||
int xfs_rtmodify_summary_int(struct xfs_rtalloc_args *args, int log,
|
||||
xfs_fileoff_t bbno, int delta, xfs_suminfo_t *sum);
|
||||
int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log,
|
||||
xfs_fileoff_t bbno, int delta);
|
||||
int xfs_rtfree_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
|
||||
xfs_rtxlen_t len);
|
||||
int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
const struct xfs_rtalloc_rec *low_rec,
|
||||
const struct xfs_rtalloc_rec *high_rec,
|
||||
xfs_rtalloc_query_range_fn fn, void *priv);
|
||||
int xfs_rtalloc_query_all(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtalloc_query_range_fn fn,
|
||||
void *priv);
|
||||
int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtxnum_t start, xfs_rtxlen_t len,
|
||||
bool *is_free);
|
||||
/*
|
||||
* Free an extent in the realtime subvolume. Length is expressed in
|
||||
* realtime extents, as is the block number.
|
||||
*/
|
||||
int /* error */
|
||||
xfs_rtfree_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_rtxnum_t start, /* starting rtext number to free */
|
||||
xfs_rtxlen_t len); /* length of extent freed */
|
||||
|
||||
/* Same as above, but in units of rt blocks. */
|
||||
int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno,
|
||||
xfs_filblks_t rtlen);
|
||||
|
||||
xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t
|
||||
rtextents);
|
||||
unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp,
|
||||
xfs_rtbxlen_t rtextents);
|
||||
|
||||
xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
|
||||
unsigned int rsumlevels, xfs_extlen_t rbmblocks);
|
||||
unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
|
||||
unsigned int rsumlevels, xfs_extlen_t rbmblocks);
|
||||
#else /* CONFIG_XFS_RT */
|
||||
# define xfs_rtfree_extent(t,b,l) (-ENOSYS)
|
||||
# define xfs_rtfree_blocks(t,rb,rl) (-ENOSYS)
|
||||
# define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS)
|
||||
# define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS)
|
||||
# define xfs_rtbitmap_read_buf(a,b) (-ENOSYS)
|
||||
# define xfs_rtsummary_read_buf(a,b) (-ENOSYS)
|
||||
# define xfs_rtbuf_cache_relse(a) (0)
|
||||
# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS)
|
||||
static inline xfs_filblks_t
|
||||
xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
|
||||
{
|
||||
/* shut up gcc */
|
||||
return 0;
|
||||
}
|
||||
# define xfs_rtbitmap_wordcount(mp, r) (0)
|
||||
# define xfs_rtsummary_blockcount(mp, l, b) (0)
|
||||
# define xfs_rtsummary_wordcount(mp, l, b) (0)
|
||||
#endif /* CONFIG_XFS_RT */
|
||||
|
||||
#endif /* __XFS_RTBITMAP_H__ */
|
@ -975,6 +975,8 @@ xfs_sb_mount_common(
|
||||
mp->m_blockmask = sbp->sb_blocksize - 1;
|
||||
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
|
||||
mp->m_blockwmask = mp->m_blockwsize - 1;
|
||||
mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
|
||||
mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
|
||||
|
||||
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
|
||||
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
|
||||
|
@ -25,7 +25,7 @@ extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp);
|
||||
|
||||
extern int xfs_update_secondary_sbs(struct xfs_mount *mp);
|
||||
|
||||
#define XFS_FS_GEOM_MAX_STRUCT_VER (4)
|
||||
#define XFS_FS_GEOM_MAX_STRUCT_VER (5)
|
||||
extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo,
|
||||
int struct_version);
|
||||
extern int xfs_sb_read_secondary(struct xfs_mount *mp,
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_qm.h"
|
||||
#include "xfs_trans_space.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
|
||||
#define _ALLOC true
|
||||
#define _FREE false
|
||||
@ -217,11 +218,12 @@ xfs_rtalloc_block_count(
|
||||
struct xfs_mount *mp,
|
||||
unsigned int num_ops)
|
||||
{
|
||||
unsigned int blksz = XFS_FSB_TO_B(mp, 1);
|
||||
unsigned int rtbmp_bytes;
|
||||
unsigned int rtbmp_blocks;
|
||||
xfs_rtxlen_t rtxlen;
|
||||
|
||||
rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY;
|
||||
return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
|
||||
rtxlen = xfs_extlen_to_rtxlen(mp, XFS_MAX_BMBT_EXTLEN);
|
||||
rtbmp_blocks = xfs_rtbitmap_blockcount(mp, rtxlen);
|
||||
return (rtbmp_blocks + 1) * num_ops;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -148,10 +148,10 @@ xfs_verify_rtbno(
|
||||
|
||||
/* Verify that a realtime device extent is fully contained inside the volume. */
|
||||
bool
|
||||
xfs_verify_rtext(
|
||||
xfs_verify_rtbext(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno,
|
||||
xfs_rtblock_t len)
|
||||
xfs_filblks_t len)
|
||||
{
|
||||
if (rtbno + len <= rtbno)
|
||||
return false;
|
||||
|
@ -11,6 +11,7 @@ typedef uint32_t prid_t; /* project ID */
|
||||
typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */
|
||||
typedef uint32_t xfs_agino_t; /* inode # within allocation grp */
|
||||
typedef uint32_t xfs_extlen_t; /* extent length in blocks */
|
||||
typedef uint32_t xfs_rtxlen_t; /* file extent length in rtextents */
|
||||
typedef uint32_t xfs_agnumber_t; /* allocation group number */
|
||||
typedef uint64_t xfs_extnum_t; /* # of extents in a file */
|
||||
typedef uint32_t xfs_aextnum_t; /* # extents in an attribute fork */
|
||||
@ -18,6 +19,7 @@ typedef int64_t xfs_fsize_t; /* bytes in a file */
|
||||
typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */
|
||||
|
||||
typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */
|
||||
typedef uint32_t xfs_rtsumoff_t; /* offset of an rtsummary info word */
|
||||
typedef uint32_t xfs_rtword_t; /* word type for bitmap manipulations */
|
||||
|
||||
typedef int64_t xfs_lsn_t; /* log sequence number */
|
||||
@ -31,6 +33,8 @@ typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */
|
||||
typedef uint64_t xfs_rtblock_t; /* extent (block) in realtime area */
|
||||
typedef uint64_t xfs_fileoff_t; /* block number in a file */
|
||||
typedef uint64_t xfs_filblks_t; /* number of blocks in a file */
|
||||
typedef uint64_t xfs_rtxnum_t; /* rtextent number */
|
||||
typedef uint64_t xfs_rtbxlen_t; /* rtbitmap extent length in rtextents */
|
||||
|
||||
typedef int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */
|
||||
|
||||
@ -47,6 +51,7 @@ typedef void * xfs_failaddr_t;
|
||||
#define NULLRFSBLOCK ((xfs_rfsblock_t)-1)
|
||||
#define NULLRTBLOCK ((xfs_rtblock_t)-1)
|
||||
#define NULLFILEOFF ((xfs_fileoff_t)-1)
|
||||
#define NULLRTEXTNO ((xfs_rtxnum_t)-1)
|
||||
|
||||
#define NULLAGBLOCK ((xfs_agblock_t)-1)
|
||||
#define NULLAGNUMBER ((xfs_agnumber_t)-1)
|
||||
@ -145,6 +150,7 @@ typedef uint32_t xfs_dqid_t;
|
||||
*/
|
||||
#define XFS_NBBYLOG 3 /* log2(NBBY) */
|
||||
#define XFS_WORDLOG 2 /* log2(sizeof(xfs_rtword_t)) */
|
||||
#define XFS_SUMINFOLOG 2 /* log2(sizeof(xfs_suminfo_t)) */
|
||||
#define XFS_NBWORDLOG (XFS_NBBYLOG + XFS_WORDLOG)
|
||||
#define XFS_NBWORD (1 << XFS_NBWORDLOG)
|
||||
#define XFS_WORDMASK ((1 << XFS_WORDLOG) - 1)
|
||||
@ -229,8 +235,8 @@ bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
|
||||
bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
|
||||
bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
|
||||
bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
|
||||
bool xfs_verify_rtext(struct xfs_mount *mp, xfs_rtblock_t rtbno,
|
||||
xfs_rtblock_t len);
|
||||
bool xfs_verify_rtbext(struct xfs_mount *mp, xfs_rtblock_t rtbno,
|
||||
xfs_filblks_t len);
|
||||
bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount);
|
||||
bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off);
|
||||
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
|
||||
|
@ -410,7 +410,7 @@ xchk_bmap_iextent(
|
||||
|
||||
/* Make sure the extent points to a valid place. */
|
||||
if (info->is_rt &&
|
||||
!xfs_verify_rtext(mp, irec->br_startblock, irec->br_blockcount))
|
||||
!xfs_verify_rtbext(mp, irec->br_startblock, irec->br_blockcount))
|
||||
xchk_fblock_set_corrupt(info->sc, info->whichfork,
|
||||
irec->br_startoff);
|
||||
if (!info->is_rt &&
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "xfs_health.h"
|
||||
#include "xfs_btree.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "scrub/scrub.h"
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "xfs_reflink.h"
|
||||
#include "xfs_rmap.h"
|
||||
#include "xfs_bmap_util.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "scrub/scrub.h"
|
||||
#include "scrub/common.h"
|
||||
#include "scrub/btree.h"
|
||||
@ -225,7 +226,7 @@ xchk_inode_extsize(
|
||||
*/
|
||||
if ((flags & XFS_DIFLAG_RTINHERIT) &&
|
||||
(flags & XFS_DIFLAG_EXTSZINHERIT) &&
|
||||
value % sc->mp->m_sb.sb_rextsize > 0)
|
||||
xfs_extlen_to_rtxmod(sc->mp, value) > 0)
|
||||
xchk_ino_set_warning(sc, ino);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "xfs_mount.h"
|
||||
#include "xfs_log_format.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "scrub/scrub.h"
|
||||
@ -48,12 +48,12 @@ xchk_rtbitmap_rec(
|
||||
{
|
||||
struct xfs_scrub *sc = priv;
|
||||
xfs_rtblock_t startblock;
|
||||
xfs_rtblock_t blockcount;
|
||||
xfs_filblks_t blockcount;
|
||||
|
||||
startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
|
||||
blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
|
||||
startblock = xfs_rtx_to_rtb(mp, rec->ar_startext);
|
||||
blockcount = xfs_rtx_to_rtb(mp, rec->ar_extcount);
|
||||
|
||||
if (!xfs_verify_rtext(mp, startblock, blockcount))
|
||||
if (!xfs_verify_rtbext(mp, startblock, blockcount))
|
||||
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
|
||||
return 0;
|
||||
}
|
||||
@ -128,26 +128,22 @@ out:
|
||||
void
|
||||
xchk_xref_is_used_rt_space(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_rtblock_t fsbno,
|
||||
xfs_rtblock_t rtbno,
|
||||
xfs_extlen_t len)
|
||||
{
|
||||
xfs_rtblock_t startext;
|
||||
xfs_rtblock_t endext;
|
||||
xfs_rtblock_t extcount;
|
||||
xfs_rtxnum_t startext;
|
||||
xfs_rtxnum_t endext;
|
||||
bool is_free;
|
||||
int error;
|
||||
|
||||
if (xchk_skip_xref(sc->sm))
|
||||
return;
|
||||
|
||||
startext = fsbno;
|
||||
endext = fsbno + len - 1;
|
||||
do_div(startext, sc->mp->m_sb.sb_rextsize);
|
||||
do_div(endext, sc->mp->m_sb.sb_rextsize);
|
||||
extcount = endext - startext + 1;
|
||||
startext = xfs_rtb_to_rtx(sc->mp, rtbno);
|
||||
endext = xfs_rtb_to_rtx(sc->mp, rtbno + len - 1);
|
||||
xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
|
||||
error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount,
|
||||
&is_free);
|
||||
error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext,
|
||||
endext - startext + 1, &is_free);
|
||||
if (!xchk_should_check_xref(sc, &error, NULL))
|
||||
goto out_unlock;
|
||||
if (is_free)
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_log_format.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "xfs_bit.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "scrub/scrub.h"
|
||||
@ -81,34 +81,45 @@ typedef unsigned int xchk_rtsumoff_t;
|
||||
static inline int
|
||||
xfsum_load(
|
||||
struct xfs_scrub *sc,
|
||||
xchk_rtsumoff_t sumoff,
|
||||
xfs_suminfo_t *info)
|
||||
xfs_rtsumoff_t sumoff,
|
||||
union xfs_suminfo_raw *rawinfo)
|
||||
{
|
||||
return xfile_obj_load(sc->xfile, info, sizeof(xfs_suminfo_t),
|
||||
return xfile_obj_load(sc->xfile, rawinfo,
|
||||
sizeof(union xfs_suminfo_raw),
|
||||
sumoff << XFS_WORDLOG);
|
||||
}
|
||||
|
||||
static inline int
|
||||
xfsum_store(
|
||||
struct xfs_scrub *sc,
|
||||
xchk_rtsumoff_t sumoff,
|
||||
const xfs_suminfo_t info)
|
||||
xfs_rtsumoff_t sumoff,
|
||||
const union xfs_suminfo_raw rawinfo)
|
||||
{
|
||||
return xfile_obj_store(sc->xfile, &info, sizeof(xfs_suminfo_t),
|
||||
return xfile_obj_store(sc->xfile, &rawinfo,
|
||||
sizeof(union xfs_suminfo_raw),
|
||||
sumoff << XFS_WORDLOG);
|
||||
}
|
||||
|
||||
static inline int
|
||||
xfsum_copyout(
|
||||
struct xfs_scrub *sc,
|
||||
xchk_rtsumoff_t sumoff,
|
||||
xfs_suminfo_t *info,
|
||||
xfs_rtsumoff_t sumoff,
|
||||
union xfs_suminfo_raw *rawinfo,
|
||||
unsigned int nr_words)
|
||||
{
|
||||
return xfile_obj_load(sc->xfile, info, nr_words << XFS_WORDLOG,
|
||||
return xfile_obj_load(sc->xfile, rawinfo, nr_words << XFS_WORDLOG,
|
||||
sumoff << XFS_WORDLOG);
|
||||
}
|
||||
|
||||
static inline xfs_suminfo_t
|
||||
xchk_rtsum_inc(
|
||||
struct xfs_mount *mp,
|
||||
union xfs_suminfo_raw *v)
|
||||
{
|
||||
v->old += 1;
|
||||
return v->old;
|
||||
}
|
||||
|
||||
/* Update the summary file to reflect the free extent that we've accumulated. */
|
||||
STATIC int
|
||||
xchk_rtsum_record_free(
|
||||
@ -121,23 +132,24 @@ xchk_rtsum_record_free(
|
||||
xfs_fileoff_t rbmoff;
|
||||
xfs_rtblock_t rtbno;
|
||||
xfs_filblks_t rtlen;
|
||||
xchk_rtsumoff_t offs;
|
||||
xfs_rtsumoff_t offs;
|
||||
unsigned int lenlog;
|
||||
xfs_suminfo_t v = 0;
|
||||
union xfs_suminfo_raw v;
|
||||
xfs_suminfo_t value;
|
||||
int error = 0;
|
||||
|
||||
if (xchk_should_terminate(sc, &error))
|
||||
return error;
|
||||
|
||||
/* Compute the relevant location in the rtsum file. */
|
||||
rbmoff = XFS_BITTOBLOCK(mp, rec->ar_startext);
|
||||
rbmoff = xfs_rtx_to_rbmblock(mp, rec->ar_startext);
|
||||
lenlog = XFS_RTBLOCKLOG(rec->ar_extcount);
|
||||
offs = XFS_SUMOFFS(mp, lenlog, rbmoff);
|
||||
offs = xfs_rtsumoffs(mp, lenlog, rbmoff);
|
||||
|
||||
rtbno = rec->ar_startext * mp->m_sb.sb_rextsize;
|
||||
rtlen = rec->ar_extcount * mp->m_sb.sb_rextsize;
|
||||
rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
|
||||
rtlen = xfs_rtx_to_rtb(mp, rec->ar_extcount);
|
||||
|
||||
if (!xfs_verify_rtext(mp, rtbno, rtlen)) {
|
||||
if (!xfs_verify_rtbext(mp, rtbno, rtlen)) {
|
||||
xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
@ -147,9 +159,9 @@ xchk_rtsum_record_free(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
v++;
|
||||
value = xchk_rtsum_inc(sc->mp, &v);
|
||||
trace_xchk_rtsum_record_free(mp, rec->ar_startext, rec->ar_extcount,
|
||||
lenlog, offs, v);
|
||||
lenlog, offs, value);
|
||||
|
||||
return xfsum_store(sc, offs, v);
|
||||
}
|
||||
@ -160,12 +172,11 @@ xchk_rtsum_compute(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
unsigned long long rtbmp_bytes;
|
||||
unsigned long long rtbmp_blocks;
|
||||
|
||||
/* If the bitmap size doesn't match the computed size, bail. */
|
||||
rtbmp_bytes = howmany_64(mp->m_sb.sb_rextents, NBBY);
|
||||
if (roundup_64(rtbmp_bytes, mp->m_sb.sb_blocksize) !=
|
||||
mp->m_rbmip->i_disk_size)
|
||||
rtbmp_blocks = xfs_rtbitmap_blockcount(mp, mp->m_sb.sb_rextents);
|
||||
if (XFS_FSB_TO_B(mp, rtbmp_blocks) != mp->m_rbmip->i_disk_size)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
return xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtsum_record_free,
|
||||
@ -177,14 +188,18 @@ STATIC int
|
||||
xchk_rtsum_compare(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_rtalloc_args args = {
|
||||
.mp = sc->mp,
|
||||
.tp = sc->tp,
|
||||
};
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_bmbt_irec map;
|
||||
xfs_fileoff_t off;
|
||||
xchk_rtsumoff_t sumoff = 0;
|
||||
int nmap;
|
||||
|
||||
for (off = 0; off < XFS_B_TO_FSB(mp, mp->m_rsumsize); off++) {
|
||||
union xfs_suminfo_raw *ondisk_info;
|
||||
int error = 0;
|
||||
|
||||
if (xchk_should_terminate(sc, &error))
|
||||
@ -205,22 +220,23 @@ xchk_rtsum_compare(
|
||||
}
|
||||
|
||||
/* Read a block's worth of ondisk rtsummary file. */
|
||||
error = xfs_rtbuf_get(mp, sc->tp, off, 1, &bp);
|
||||
error = xfs_rtsummary_read_buf(&args, off);
|
||||
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
|
||||
return error;
|
||||
|
||||
/* Read a block's worth of computed rtsummary file. */
|
||||
error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize);
|
||||
if (error) {
|
||||
xfs_trans_brelse(sc->tp, bp);
|
||||
xfs_rtbuf_cache_relse(&args);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (memcmp(bp->b_addr, sc->buf,
|
||||
ondisk_info = xfs_rsumblock_infoptr(&args, 0);
|
||||
if (memcmp(ondisk_info, sc->buf,
|
||||
mp->m_blockwsize << XFS_WORDLOG) != 0)
|
||||
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
|
||||
|
||||
xfs_trans_brelse(sc->tp, bp);
|
||||
xfs_rtbuf_cache_relse(&args);
|
||||
sumoff += mp->m_blockwsize;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_btree.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "scrub/scrub.h"
|
||||
#include "scrub/xfile.h"
|
||||
#include "scrub/xfarray.h"
|
||||
|
@ -1036,17 +1036,18 @@ TRACE_EVENT(xfarray_sort_stats,
|
||||
|
||||
#ifdef CONFIG_XFS_RT
|
||||
TRACE_EVENT(xchk_rtsum_record_free,
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_rtblock_t start,
|
||||
uint64_t len, unsigned int log, loff_t pos, xfs_suminfo_t v),
|
||||
TP_ARGS(mp, start, len, log, pos, v),
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_rtxnum_t start,
|
||||
xfs_rtbxlen_t len, unsigned int log, loff_t pos,
|
||||
xfs_suminfo_t value),
|
||||
TP_ARGS(mp, start, len, log, pos, value),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(dev_t, rtdev)
|
||||
__field(xfs_rtblock_t, start)
|
||||
__field(xfs_rtxnum_t, start)
|
||||
__field(unsigned long long, len)
|
||||
__field(unsigned int, log)
|
||||
__field(loff_t, pos)
|
||||
__field(xfs_suminfo_t, v)
|
||||
__field(xfs_suminfo_t, value)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = mp->m_super->s_dev;
|
||||
@ -1055,7 +1056,7 @@ TRACE_EVENT(xchk_rtsum_record_free,
|
||||
__entry->len = len;
|
||||
__entry->log = log;
|
||||
__entry->pos = pos;
|
||||
__entry->v = v;
|
||||
__entry->value = value;
|
||||
),
|
||||
TP_printk("dev %d:%d rtdev %d:%d rtx 0x%llx rtxcount 0x%llx log %u rsumpos 0x%llx sumcount %u",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
@ -1064,7 +1065,7 @@ TRACE_EVENT(xchk_rtsum_record_free,
|
||||
__entry->len,
|
||||
__entry->log,
|
||||
__entry->pos,
|
||||
__entry->v)
|
||||
__entry->value)
|
||||
);
|
||||
#endif /* CONFIG_XFS_RT */
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_iomap.h"
|
||||
#include "xfs_reflink.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
|
||||
/* Kernel only BMAP related definitions and functions */
|
||||
|
||||
@ -75,28 +76,28 @@ xfs_bmap_rtalloc(
|
||||
{
|
||||
struct xfs_mount *mp = ap->ip->i_mount;
|
||||
xfs_fileoff_t orig_offset = ap->offset;
|
||||
xfs_rtblock_t rtb;
|
||||
xfs_extlen_t prod = 0; /* product factor for allocators */
|
||||
xfs_rtxnum_t rtx;
|
||||
xfs_rtxlen_t prod = 0; /* product factor for allocators */
|
||||
xfs_extlen_t mod = 0; /* product factor for allocators */
|
||||
xfs_extlen_t ralen = 0; /* realtime allocation length */
|
||||
xfs_rtxlen_t ralen = 0; /* realtime allocation length */
|
||||
xfs_extlen_t align; /* minimum allocation alignment */
|
||||
xfs_extlen_t orig_length = ap->length;
|
||||
xfs_extlen_t minlen = mp->m_sb.sb_rextsize;
|
||||
xfs_extlen_t raminlen;
|
||||
xfs_rtxlen_t raminlen;
|
||||
bool rtlocked = false;
|
||||
bool ignore_locality = false;
|
||||
int error;
|
||||
|
||||
align = xfs_get_extsz_hint(ap->ip);
|
||||
retry:
|
||||
prod = align / mp->m_sb.sb_rextsize;
|
||||
prod = xfs_extlen_to_rtxlen(mp, align);
|
||||
error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
|
||||
align, 1, ap->eof, 0,
|
||||
ap->conv, &ap->offset, &ap->length);
|
||||
if (error)
|
||||
return error;
|
||||
ASSERT(ap->length);
|
||||
ASSERT(ap->length % mp->m_sb.sb_rextsize == 0);
|
||||
ASSERT(xfs_extlen_to_rtxmod(mp, ap->length) == 0);
|
||||
|
||||
/*
|
||||
* If we shifted the file offset downward to satisfy an extent size
|
||||
@ -116,17 +117,14 @@ retry:
|
||||
prod = 1;
|
||||
/*
|
||||
* Set ralen to be the actual requested length in rtextents.
|
||||
*/
|
||||
ralen = ap->length / mp->m_sb.sb_rextsize;
|
||||
/*
|
||||
*
|
||||
* If the old value was close enough to XFS_BMBT_MAX_EXTLEN that
|
||||
* we rounded up to it, cut it back so it's valid again.
|
||||
* Note that if it's a really large request (bigger than
|
||||
* XFS_BMBT_MAX_EXTLEN), we don't hear about that number, and can't
|
||||
* adjust the starting point to match it.
|
||||
*/
|
||||
if (ralen * mp->m_sb.sb_rextsize >= XFS_MAX_BMBT_EXTLEN)
|
||||
ralen = XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize;
|
||||
ralen = xfs_extlen_to_rtxlen(mp, min(ap->length, XFS_MAX_BMBT_EXTLEN));
|
||||
|
||||
/*
|
||||
* Lock out modifications to both the RT bitmap and summary inodes
|
||||
@ -144,12 +142,10 @@ retry:
|
||||
* pick an extent that will space things out in the rt area.
|
||||
*/
|
||||
if (ap->eof && ap->offset == 0) {
|
||||
xfs_rtblock_t rtx; /* realtime extent no */
|
||||
|
||||
error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
|
||||
if (error)
|
||||
return error;
|
||||
ap->blkno = rtx * mp->m_sb.sb_rextsize;
|
||||
ap->blkno = xfs_rtx_to_rtb(mp, rtx);
|
||||
} else {
|
||||
ap->blkno = 0;
|
||||
}
|
||||
@ -160,20 +156,18 @@ retry:
|
||||
* Realtime allocation, done through xfs_rtallocate_extent.
|
||||
*/
|
||||
if (ignore_locality)
|
||||
ap->blkno = 0;
|
||||
rtx = 0;
|
||||
else
|
||||
do_div(ap->blkno, mp->m_sb.sb_rextsize);
|
||||
rtb = ap->blkno;
|
||||
ap->length = ralen;
|
||||
raminlen = max_t(xfs_extlen_t, 1, minlen / mp->m_sb.sb_rextsize);
|
||||
error = xfs_rtallocate_extent(ap->tp, ap->blkno, raminlen, ap->length,
|
||||
&ralen, ap->wasdel, prod, &rtb);
|
||||
rtx = xfs_rtb_to_rtx(mp, ap->blkno);
|
||||
raminlen = max_t(xfs_rtxlen_t, 1, xfs_extlen_to_rtxlen(mp, minlen));
|
||||
error = xfs_rtallocate_extent(ap->tp, rtx, raminlen, ralen, &ralen,
|
||||
ap->wasdel, prod, &rtx);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (rtb != NULLRTBLOCK) {
|
||||
ap->blkno = rtb * mp->m_sb.sb_rextsize;
|
||||
ap->length = ralen * mp->m_sb.sb_rextsize;
|
||||
if (rtx != NULLRTEXTNO) {
|
||||
ap->blkno = xfs_rtx_to_rtb(mp, rtx);
|
||||
ap->length = xfs_rtxlen_to_extlen(mp, ralen);
|
||||
ap->ip->i_nblocks += ap->length;
|
||||
xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
|
||||
if (ap->wasdel)
|
||||
@ -690,7 +684,7 @@ xfs_can_free_eofblocks(
|
||||
*/
|
||||
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
|
||||
if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1)
|
||||
end_fsb = roundup_64(end_fsb, mp->m_sb.sb_rextsize);
|
||||
end_fsb = xfs_rtb_roundup_rtx(mp, end_fsb);
|
||||
last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||
if (last_fsb <= end_fsb)
|
||||
return false;
|
||||
@ -780,12 +774,10 @@ xfs_alloc_file_space(
|
||||
{
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
xfs_off_t count;
|
||||
xfs_filblks_t allocated_fsb;
|
||||
xfs_filblks_t allocatesize_fsb;
|
||||
xfs_extlen_t extsz, temp;
|
||||
xfs_fileoff_t startoffset_fsb;
|
||||
xfs_fileoff_t endoffset_fsb;
|
||||
int nimaps;
|
||||
int rt;
|
||||
xfs_trans_t *tp;
|
||||
xfs_bmbt_irec_t imaps[1], *imapp;
|
||||
@ -808,7 +800,6 @@ xfs_alloc_file_space(
|
||||
|
||||
count = len;
|
||||
imapp = &imaps[0];
|
||||
nimaps = 1;
|
||||
startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
|
||||
allocatesize_fsb = endoffset_fsb - startoffset_fsb;
|
||||
@ -819,6 +810,7 @@ xfs_alloc_file_space(
|
||||
while (allocatesize_fsb && !error) {
|
||||
xfs_fileoff_t s, e;
|
||||
unsigned int dblocks, rblocks, resblks;
|
||||
int nimaps = 1;
|
||||
|
||||
/*
|
||||
* Determine space reservations for data/realtime.
|
||||
@ -884,15 +876,19 @@ xfs_alloc_file_space(
|
||||
if (error)
|
||||
break;
|
||||
|
||||
allocated_fsb = imapp->br_blockcount;
|
||||
|
||||
if (nimaps == 0) {
|
||||
error = -ENOSPC;
|
||||
break;
|
||||
/*
|
||||
* If the allocator cannot find a single free extent large
|
||||
* enough to cover the start block of the requested range,
|
||||
* xfs_bmapi_write will return 0 but leave *nimaps set to 0.
|
||||
*
|
||||
* In that case we simply need to keep looping with the same
|
||||
* startoffset_fsb so that one of the following allocations
|
||||
* will eventually reach the requested range.
|
||||
*/
|
||||
if (nimaps) {
|
||||
startoffset_fsb += imapp->br_blockcount;
|
||||
allocatesize_fsb -= imapp->br_blockcount;
|
||||
}
|
||||
|
||||
startoffset_fsb += allocated_fsb;
|
||||
allocatesize_fsb -= allocated_fsb;
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -989,10 +985,8 @@ xfs_free_file_space(
|
||||
|
||||
/* We can only free complete realtime extents. */
|
||||
if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) {
|
||||
startoffset_fsb = roundup_64(startoffset_fsb,
|
||||
mp->m_sb.sb_rextsize);
|
||||
endoffset_fsb = rounddown_64(endoffset_fsb,
|
||||
mp->m_sb.sb_rextsize);
|
||||
startoffset_fsb = xfs_rtb_roundup_rtx(mp, startoffset_fsb);
|
||||
endoffset_fsb = xfs_rtb_rounddown_rtx(mp, endoffset_fsb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -214,6 +214,43 @@ xfs_ilock_iocb(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_ilock_iocb_for_write(
|
||||
struct kiocb *iocb,
|
||||
unsigned int *lock_mode)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
|
||||
|
||||
ret = xfs_ilock_iocb(iocb, *lock_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (*lock_mode == XFS_IOLOCK_EXCL)
|
||||
return 0;
|
||||
if (!xfs_iflags_test(ip, XFS_IREMAPPING))
|
||||
return 0;
|
||||
|
||||
xfs_iunlock(ip, *lock_mode);
|
||||
*lock_mode = XFS_IOLOCK_EXCL;
|
||||
return xfs_ilock_iocb(iocb, *lock_mode);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
xfs_ilock_for_write_fault(
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
/* get a shared lock if no remapping in progress */
|
||||
xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
|
||||
if (!xfs_iflags_test(ip, XFS_IREMAPPING))
|
||||
return XFS_MMAPLOCK_SHARED;
|
||||
|
||||
/* wait for remapping to complete */
|
||||
xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
|
||||
xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
|
||||
return XFS_MMAPLOCK_EXCL;
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
xfs_file_dio_read(
|
||||
struct kiocb *iocb,
|
||||
@ -551,7 +588,7 @@ xfs_file_dio_write_aligned(
|
||||
unsigned int iolock = XFS_IOLOCK_SHARED;
|
||||
ssize_t ret;
|
||||
|
||||
ret = xfs_ilock_iocb(iocb, iolock);
|
||||
ret = xfs_ilock_iocb_for_write(iocb, &iolock);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = xfs_file_write_checks(iocb, from, &iolock);
|
||||
@ -618,7 +655,7 @@ retry_exclusive:
|
||||
flags = IOMAP_DIO_FORCE_WAIT;
|
||||
}
|
||||
|
||||
ret = xfs_ilock_iocb(iocb, iolock);
|
||||
ret = xfs_ilock_iocb_for_write(iocb, &iolock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1180,7 +1217,7 @@ xfs_file_remap_range(
|
||||
if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out))
|
||||
xfs_log_force_inode(dest);
|
||||
out_unlock:
|
||||
xfs_iunlock2_io_mmap(src, dest);
|
||||
xfs_iunlock2_remapping(src, dest);
|
||||
if (ret)
|
||||
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
|
||||
return remapped > 0 ? remapped : ret;
|
||||
@ -1328,6 +1365,7 @@ __xfs_filemap_fault(
|
||||
struct inode *inode = file_inode(vmf->vma->vm_file);
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
vm_fault_t ret;
|
||||
unsigned int lock_mode = 0;
|
||||
|
||||
trace_xfs_filemap_fault(ip, order, write_fault);
|
||||
|
||||
@ -1336,25 +1374,24 @@ __xfs_filemap_fault(
|
||||
file_update_time(vmf->vma->vm_file);
|
||||
}
|
||||
|
||||
if (IS_DAX(inode) || write_fault)
|
||||
lock_mode = xfs_ilock_for_write_fault(XFS_I(inode));
|
||||
|
||||
if (IS_DAX(inode)) {
|
||||
pfn_t pfn;
|
||||
|
||||
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
ret = xfs_dax_fault(vmf, order, write_fault, &pfn);
|
||||
if (ret & VM_FAULT_NEEDDSYNC)
|
||||
ret = dax_finish_sync_fault(vmf, order, pfn);
|
||||
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
} else if (write_fault) {
|
||||
ret = iomap_page_mkwrite(vmf, &xfs_page_mkwrite_iomap_ops);
|
||||
} else {
|
||||
if (write_fault) {
|
||||
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
ret = iomap_page_mkwrite(vmf,
|
||||
&xfs_page_mkwrite_iomap_ops);
|
||||
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
} else {
|
||||
ret = filemap_fault(vmf);
|
||||
}
|
||||
ret = filemap_fault(vmf);
|
||||
}
|
||||
|
||||
if (lock_mode)
|
||||
xfs_iunlock(XFS_I(inode), lock_mode);
|
||||
|
||||
if (write_fault)
|
||||
sb_end_pagefault(inode->i_sb);
|
||||
return ret;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "xfs_refcount.h"
|
||||
#include "xfs_refcount_btree.h"
|
||||
#include "xfs_alloc_btree.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "xfs_ag.h"
|
||||
|
||||
/* Convert an xfs_fsmap to an fsmap. */
|
||||
@ -483,11 +483,11 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
|
||||
xfs_rtblock_t rtbno;
|
||||
xfs_daddr_t rec_daddr, len_daddr;
|
||||
|
||||
rtbno = rec->ar_startext * mp->m_sb.sb_rextsize;
|
||||
rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
|
||||
rec_daddr = XFS_FSB_TO_BB(mp, rtbno);
|
||||
irec.rm_startblock = rtbno;
|
||||
|
||||
rtbno = rec->ar_extcount * mp->m_sb.sb_rextsize;
|
||||
rtbno = xfs_rtx_to_rtb(mp, rec->ar_extcount);
|
||||
len_daddr = XFS_FSB_TO_BB(mp, rtbno);
|
||||
irec.rm_blockcount = rtbno;
|
||||
|
||||
@ -514,7 +514,7 @@ xfs_getfsmap_rtdev_rtbitmap(
|
||||
uint64_t eofs;
|
||||
int error;
|
||||
|
||||
eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rextents * mp->m_sb.sb_rextsize);
|
||||
eofs = XFS_FSB_TO_BB(mp, xfs_rtx_to_rtb(mp, mp->m_sb.sb_rextents));
|
||||
if (keys[0].fmr_physical >= eofs)
|
||||
return 0;
|
||||
start_rtb = XFS_BB_TO_FSBT(mp,
|
||||
@ -539,11 +539,8 @@ xfs_getfsmap_rtdev_rtbitmap(
|
||||
* Set up query parameters to return free rtextents covering the range
|
||||
* we want.
|
||||
*/
|
||||
alow.ar_startext = start_rtb;
|
||||
ahigh.ar_startext = end_rtb;
|
||||
do_div(alow.ar_startext, mp->m_sb.sb_rextsize);
|
||||
if (do_div(ahigh.ar_startext, mp->m_sb.sb_rextsize))
|
||||
ahigh.ar_startext++;
|
||||
alow.ar_startext = xfs_rtb_to_rtx(mp, start_rtb);
|
||||
ahigh.ar_startext = xfs_rtb_to_rtxup(mp, end_rtb);
|
||||
error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
|
||||
xfs_getfsmap_rtdev_rtbitmap_helper, info);
|
||||
if (error)
|
||||
|
@ -918,6 +918,13 @@ xfs_droplink(
|
||||
xfs_trans_t *tp,
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
if (VFS_I(ip)->i_nlink == 0) {
|
||||
xfs_alert(ip->i_mount,
|
||||
"%s: Attempt to drop inode (%llu) with nlink zero.",
|
||||
__func__, ip->i_ino);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
|
||||
|
||||
drop_nlink(VFS_I(ip));
|
||||
@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap(
|
||||
inode_unlock(VFS_I(ip1));
|
||||
}
|
||||
|
||||
/* Drop the MMAPLOCK and the IOLOCK after a remap completes. */
|
||||
void
|
||||
xfs_iunlock2_remapping(
|
||||
struct xfs_inode *ip1,
|
||||
struct xfs_inode *ip2)
|
||||
{
|
||||
xfs_iflags_clear(ip1, XFS_IREMAPPING);
|
||||
|
||||
if (ip1 != ip2)
|
||||
xfs_iunlock(ip1, XFS_MMAPLOCK_SHARED);
|
||||
xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
|
||||
|
||||
if (ip1 != ip2)
|
||||
inode_unlock_shared(VFS_I(ip1));
|
||||
inode_unlock(VFS_I(ip2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reload the incore inode list for this inode. Caller should ensure that
|
||||
* the link count cannot change, either by taking ILOCK_SHARED or otherwise
|
||||
|
@ -347,6 +347,14 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
|
||||
/* Quotacheck is running but inode has not been added to quota counts. */
|
||||
#define XFS_IQUOTAUNCHECKED (1 << 14)
|
||||
|
||||
/*
|
||||
* Remap in progress. Callers that wish to update file data while
|
||||
* holding a shared IOLOCK or MMAPLOCK must drop the lock and retake
|
||||
* the lock in exclusive mode. Relocking the file will block until
|
||||
* IREMAPPING is cleared.
|
||||
*/
|
||||
#define XFS_IREMAPPING (1U << 15)
|
||||
|
||||
/* All inode state flags related to inode reclaim. */
|
||||
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
|
||||
XFS_IRECLAIM | \
|
||||
@ -595,6 +603,7 @@ void xfs_end_io(struct work_struct *work);
|
||||
|
||||
int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
|
||||
void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
|
||||
void xfs_iunlock2_remapping(struct xfs_inode *ip1, struct xfs_inode *ip2);
|
||||
|
||||
static inline bool
|
||||
xfs_inode_unlinked_incomplete(
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_log_priv.h"
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
|
||||
#include <linux/iversion.h>
|
||||
|
||||
@ -107,7 +108,7 @@ xfs_inode_item_precommit(
|
||||
*/
|
||||
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
|
||||
(ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
|
||||
(ip->i_extsize % ip->i_mount->m_sb.sb_rextsize) > 0) {
|
||||
xfs_extlen_to_rtxmod(ip->i_mount, ip->i_extsize) > 0) {
|
||||
ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
|
||||
XFS_DIFLAG_EXTSZINHERIT);
|
||||
ip->i_extsize = 0;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "xfs_reflink.h"
|
||||
#include "xfs_ioctl.h"
|
||||
#include "xfs_xattr.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
|
||||
#include <linux/mount.h>
|
||||
#include <linux/namei.h>
|
||||
@ -1004,7 +1005,7 @@ xfs_fill_fsxattr(
|
||||
* later.
|
||||
*/
|
||||
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
|
||||
ip->i_extsize % mp->m_sb.sb_rextsize > 0) {
|
||||
xfs_extlen_to_rtxmod(mp, ip->i_extsize) > 0) {
|
||||
fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE |
|
||||
FS_XFLAG_EXTSZINHERIT);
|
||||
fa->fsx_extsize = 0;
|
||||
@ -1130,7 +1131,7 @@ xfs_ioctl_setattr_xflags(
|
||||
/* If realtime flag is set then must have realtime device */
|
||||
if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
|
||||
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
|
||||
(ip->i_extsize % mp->m_sb.sb_rextsize))
|
||||
xfs_extlen_to_rtxmod(mp, ip->i_extsize))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -198,6 +198,18 @@ static inline uint64_t howmany_64(uint64_t x, uint32_t y)
|
||||
return x;
|
||||
}
|
||||
|
||||
/* If @b is a power of 2, return log2(b). Else return -1. */
|
||||
static inline int8_t log2_if_power2(unsigned long b)
|
||||
{
|
||||
return is_power_of_2(b) ? ilog2(b) : -1;
|
||||
}
|
||||
|
||||
/* If @b is a power of 2, return a mask of the lower bits, else return zero. */
|
||||
static inline unsigned long long mask64_if_power2(unsigned long b)
|
||||
{
|
||||
return is_power_of_2(b) ? b - 1 : 0;
|
||||
}
|
||||
|
||||
int xfs_rw_bdev(struct block_device *bdev, sector_t sector, unsigned int count,
|
||||
char *data, enum req_op op);
|
||||
|
||||
|
@ -101,9 +101,9 @@ typedef struct xfs_mount {
|
||||
|
||||
/*
|
||||
* Optional cache of rt summary level per bitmap block with the
|
||||
* invariant that m_rsum_cache[bbno] <= the minimum i for which
|
||||
* rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip
|
||||
* inode lock.
|
||||
* invariant that m_rsum_cache[bbno] > the maximum i for which
|
||||
* rsum[i][bbno] != 0, or 0 if rsum[i][bbno] == 0 for all i.
|
||||
* Reads and writes are serialized by the rsumip inode lock.
|
||||
*/
|
||||
uint8_t *m_rsum_cache;
|
||||
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
|
||||
@ -119,6 +119,7 @@ typedef struct xfs_mount {
|
||||
uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
|
||||
uint8_t m_agno_log; /* log #ag's */
|
||||
uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
|
||||
int8_t m_rtxblklog; /* log2 of rextsize, if possible */
|
||||
uint m_blockmask; /* sb_blocksize-1 */
|
||||
uint m_blockwsize; /* sb_blocksize in words */
|
||||
uint m_blockwmask; /* blockwsize-1 */
|
||||
@ -152,6 +153,7 @@ typedef struct xfs_mount {
|
||||
uint64_t m_features; /* active filesystem features */
|
||||
uint64_t m_low_space[XFS_LOWSP_MAX];
|
||||
uint64_t m_low_rtexts[XFS_LOWSP_MAX];
|
||||
uint64_t m_rtxblkmask; /* rt extent block mask */
|
||||
struct xfs_ino_geometry m_ino_geo; /* inode geometry */
|
||||
struct xfs_trans_resv m_resv; /* precomputed res values */
|
||||
/* low free space thresholds */
|
||||
|
@ -72,6 +72,10 @@ xfs_check_ondisk_structs(void)
|
||||
XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_map_t, 4);
|
||||
XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_local_t, 4);
|
||||
|
||||
/* realtime structures */
|
||||
XFS_CHECK_STRUCT_SIZE(union xfs_rtword_raw, 4);
|
||||
XFS_CHECK_STRUCT_SIZE(union xfs_suminfo_raw, 4);
|
||||
|
||||
/*
|
||||
* m68k has problems with xfs_attr_leaf_name_remote_t, but we pad it to
|
||||
* 4 bytes anyway so it's not obviously a problem. Hence for the moment
|
||||
|
@ -1540,6 +1540,10 @@ xfs_reflink_remap_prep(
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
xfs_iflags_set(src, XFS_IREMAPPING);
|
||||
if (inode_in != inode_out)
|
||||
xfs_ilock_demote(src, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
|
||||
|
||||
return 0;
|
||||
out_unlock:
|
||||
xfs_iunlock2_io_mmap(src, dest);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,22 +11,6 @@
|
||||
struct xfs_mount;
|
||||
struct xfs_trans;
|
||||
|
||||
/*
|
||||
* XXX: Most of the realtime allocation functions deal in units of realtime
|
||||
* extents, not realtime blocks. This looks funny when paired with the type
|
||||
* name and screams for a larger cleanup.
|
||||
*/
|
||||
struct xfs_rtalloc_rec {
|
||||
xfs_rtblock_t ar_startext;
|
||||
xfs_rtblock_t ar_extcount;
|
||||
};
|
||||
|
||||
typedef int (*xfs_rtalloc_query_range_fn)(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
const struct xfs_rtalloc_rec *rec,
|
||||
void *priv);
|
||||
|
||||
#ifdef CONFIG_XFS_RT
|
||||
/*
|
||||
* Function prototypes for exported functions.
|
||||
@ -40,23 +24,14 @@ typedef int (*xfs_rtalloc_query_range_fn)(
|
||||
int /* error */
|
||||
xfs_rtallocate_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_rtblock_t bno, /* starting block number to allocate */
|
||||
xfs_extlen_t minlen, /* minimum length to allocate */
|
||||
xfs_extlen_t maxlen, /* maximum length to allocate */
|
||||
xfs_extlen_t *len, /* out: actual length allocated */
|
||||
xfs_rtxnum_t start, /* starting rtext number to allocate */
|
||||
xfs_rtxlen_t minlen, /* minimum length to allocate */
|
||||
xfs_rtxlen_t maxlen, /* maximum length to allocate */
|
||||
xfs_rtxlen_t *len, /* out: actual length allocated */
|
||||
int wasdel, /* was a delayed allocation extent */
|
||||
xfs_extlen_t prod, /* extent product factor */
|
||||
xfs_rtblock_t *rtblock); /* out: start block allocated */
|
||||
xfs_rtxlen_t prod, /* extent product factor */
|
||||
xfs_rtxnum_t *rtblock); /* out: start rtext allocated */
|
||||
|
||||
/*
|
||||
* Free an extent in the realtime subvolume. Length is expressed in
|
||||
* realtime extents, as is the block number.
|
||||
*/
|
||||
int /* error */
|
||||
xfs_rtfree_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_rtblock_t bno, /* starting block number to free */
|
||||
xfs_extlen_t len); /* length of extent freed */
|
||||
|
||||
/*
|
||||
* Initialize realtime fields in the mount structure.
|
||||
@ -87,8 +62,8 @@ int /* error */
|
||||
xfs_rtpick_extent(
|
||||
struct xfs_mount *mp, /* file system mount point */
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_extlen_t len, /* allocation length (rtextents) */
|
||||
xfs_rtblock_t *pick); /* result rt extent */
|
||||
xfs_rtxlen_t len, /* allocation length (rtextents) */
|
||||
xfs_rtxnum_t *pick); /* result rt extent */
|
||||
|
||||
/*
|
||||
* Grow the realtime area of the filesystem.
|
||||
@ -98,55 +73,12 @@ xfs_growfs_rt(
|
||||
struct xfs_mount *mp, /* file system mount structure */
|
||||
xfs_growfs_rt_t *in); /* user supplied growfs struct */
|
||||
|
||||
/*
|
||||
* From xfs_rtbitmap.c
|
||||
*/
|
||||
int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t block, int issum, struct xfs_buf **bpp);
|
||||
int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t start, xfs_extlen_t len, int val,
|
||||
xfs_rtblock_t *new, int *stat);
|
||||
int xfs_rtfind_back(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t start, xfs_rtblock_t limit,
|
||||
xfs_rtblock_t *rtblock);
|
||||
int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t start, xfs_rtblock_t limit,
|
||||
xfs_rtblock_t *rtblock);
|
||||
int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t start, xfs_extlen_t len, int val);
|
||||
int xfs_rtmodify_summary_int(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
int log, xfs_rtblock_t bbno, int delta,
|
||||
struct xfs_buf **rbpp, xfs_fsblock_t *rsb,
|
||||
xfs_suminfo_t *sum);
|
||||
int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log,
|
||||
xfs_rtblock_t bbno, int delta, struct xfs_buf **rbpp,
|
||||
xfs_fsblock_t *rsb);
|
||||
int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t start, xfs_extlen_t len,
|
||||
struct xfs_buf **rbpp, xfs_fsblock_t *rsb);
|
||||
int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
const struct xfs_rtalloc_rec *low_rec,
|
||||
const struct xfs_rtalloc_rec *high_rec,
|
||||
xfs_rtalloc_query_range_fn fn, void *priv);
|
||||
int xfs_rtalloc_query_all(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtalloc_query_range_fn fn,
|
||||
void *priv);
|
||||
bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
|
||||
int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtblock_t start, xfs_extlen_t len,
|
||||
bool *is_free);
|
||||
int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp);
|
||||
#else
|
||||
# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (ENOSYS)
|
||||
# define xfs_rtfree_extent(t,b,l) (ENOSYS)
|
||||
# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS)
|
||||
# define xfs_growfs_rt(mp,in) (ENOSYS)
|
||||
# define xfs_rtalloc_query_range(t,l,h,f,p) (ENOSYS)
|
||||
# define xfs_rtalloc_query_all(m,t,f,p) (ENOSYS)
|
||||
# define xfs_rtbuf_get(m,t,b,i,p) (ENOSYS)
|
||||
# define xfs_verify_rtbno(m, r) (false)
|
||||
# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (ENOSYS)
|
||||
# define xfs_rtalloc_reinit_frextents(m) (0)
|
||||
# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (-ENOSYS)
|
||||
# define xfs_rtpick_extent(m,t,l,rb) (-ENOSYS)
|
||||
# define xfs_growfs_rt(mp,in) (-ENOSYS)
|
||||
# define xfs_rtalloc_reinit_frextents(m) (0)
|
||||
static inline int /* error */
|
||||
xfs_rtmount_init(
|
||||
xfs_mount_t *mp) /* file system mount structure */
|
||||
@ -157,7 +89,7 @@ xfs_rtmount_init(
|
||||
xfs_warn(mp, "Not built with CONFIG_XFS_RT");
|
||||
return -ENOSYS;
|
||||
}
|
||||
# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
|
||||
# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (-ENOSYS))
|
||||
# define xfs_rtunmount_inodes(m)
|
||||
#endif /* CONFIG_XFS_RT */
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "xfs_xattr.h"
|
||||
#include "xfs_iunlink_item.h"
|
||||
#include "xfs_dahash_test.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
#include "scrub/stats.h"
|
||||
|
||||
#include <linux/magic.h>
|
||||
@ -896,7 +897,7 @@ xfs_fs_statfs(
|
||||
|
||||
statp->f_blocks = sbp->sb_rblocks;
|
||||
freertx = percpu_counter_sum_positive(&mp->m_frextents);
|
||||
statp->f_bavail = statp->f_bfree = freertx * sbp->sb_rextsize;
|
||||
statp->f_bavail = statp->f_bfree = xfs_rtx_to_rtb(mp, freertx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "xfs_dquot_item.h"
|
||||
#include "xfs_dquot.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_rtbitmap.h"
|
||||
|
||||
struct kmem_cache *xfs_trans_cache;
|
||||
|
||||
@ -655,6 +656,10 @@ xfs_trans_unreserve_and_mod_sb(
|
||||
mp->m_sb.sb_agcount += tp->t_agcount_delta;
|
||||
mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta;
|
||||
mp->m_sb.sb_rextsize += tp->t_rextsize_delta;
|
||||
if (tp->t_rextsize_delta) {
|
||||
mp->m_rtxblklog = log2_if_power2(mp->m_sb.sb_rextsize);
|
||||
mp->m_rtxblkmask = mask64_if_power2(mp->m_sb.sb_rextsize);
|
||||
}
|
||||
mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta;
|
||||
mp->m_sb.sb_rblocks += tp->t_rblocks_delta;
|
||||
mp->m_sb.sb_rextents += tp->t_rextents_delta;
|
||||
@ -1196,7 +1201,7 @@ xfs_trans_alloc_inode(
|
||||
|
||||
retry:
|
||||
error = xfs_trans_alloc(mp, resv, dblocks,
|
||||
rblocks / mp->m_sb.sb_rextsize,
|
||||
xfs_extlen_to_rtxlen(mp, rblocks),
|
||||
force ? XFS_TRANS_RESERVE : 0, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
Loading…
Reference in New Issue
Block a user