Commit 34f76326 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 6d795e2a 14a53798
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_bmap_util.h" #include "xfs_bmap_util.h"
#include "xfs_bmap_btree.h" #include "xfs_bmap_btree.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_errortag.h" #include "xfs_errortag.h"
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_quota.h" #include "xfs_quota.h"
...@@ -2989,7 +2989,7 @@ xfs_bmap_extsize_align( ...@@ -2989,7 +2989,7 @@ xfs_bmap_extsize_align(
* If realtime, and the result isn't a multiple of the realtime * If realtime, and the result isn't a multiple of the realtime
* extent size we need to remove blocks until it is. * 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're not covering the original request, or
* we won't be able to once we fix the length. * we won't be able to once we fix the length.
...@@ -3016,7 +3016,7 @@ xfs_bmap_extsize_align( ...@@ -3016,7 +3016,7 @@ xfs_bmap_extsize_align(
else { else {
align_alen -= orig_off - align_off; align_alen -= orig_off - align_off;
align_off = orig_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. * Result doesn't cover the request, fail it.
...@@ -4826,12 +4826,8 @@ xfs_bmap_del_extent_delay( ...@@ -4826,12 +4826,8 @@ xfs_bmap_del_extent_delay(
ASSERT(got->br_startoff <= del->br_startoff); ASSERT(got->br_startoff <= del->br_startoff);
ASSERT(got_endoff >= del_endoff); ASSERT(got_endoff >= del_endoff);
if (isrt) { if (isrt)
uint64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount); xfs_mod_frextents(mp, xfs_rtb_to_rtx(mp, del->br_blockcount));
do_div(rtexts, mp->m_sb.sb_rextsize);
xfs_mod_frextents(mp, rtexts);
}
/* /*
* Update the inode delalloc counter now and wait to update the * Update the inode delalloc counter now and wait to update the
...@@ -5057,33 +5053,20 @@ xfs_bmap_del_extent_real( ...@@ -5057,33 +5053,20 @@ xfs_bmap_del_extent_real(
flags = XFS_ILOG_CORE; flags = XFS_ILOG_CORE;
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) { 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)) { if (!(bflags & XFS_BMAPI_REMAP)) {
xfs_fsblock_t bno; error = xfs_rtfree_blocks(tp, del->br_startblock,
del->br_blockcount);
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);
if (error) if (error)
goto done; goto done;
} }
do_fx = 0; do_fx = 0;
nblks = len * mp->m_sb.sb_rextsize;
qfield = XFS_TRANS_DQ_RTBCOUNT; qfield = XFS_TRANS_DQ_RTBCOUNT;
} else { } else {
do_fx = 1; do_fx = 1;
nblks = del->br_blockcount;
qfield = XFS_TRANS_DQ_BCOUNT; qfield = XFS_TRANS_DQ_BCOUNT;
} }
nblks = del->br_blockcount;
del_endblock = del->br_startblock + del->br_blockcount; del_endblock = del->br_startblock + del->br_blockcount;
if (cur) { if (cur) {
...@@ -5289,7 +5272,6 @@ __xfs_bunmapi( ...@@ -5289,7 +5272,6 @@ __xfs_bunmapi(
int tmp_logflags; /* partial logging flags */ int tmp_logflags; /* partial logging flags */
int wasdel; /* was a delayed alloc extent */ int wasdel; /* was a delayed alloc extent */
int whichfork; /* data or attribute fork */ int whichfork; /* data or attribute fork */
xfs_fsblock_t sum;
xfs_filblks_t len = *rlen; /* length to unmap in file */ xfs_filblks_t len = *rlen; /* length to unmap in file */
xfs_fileoff_t end; xfs_fileoff_t end;
struct xfs_iext_cursor icur; struct xfs_iext_cursor icur;
...@@ -5384,8 +5366,8 @@ __xfs_bunmapi( ...@@ -5384,8 +5366,8 @@ __xfs_bunmapi(
if (!isrt) if (!isrt)
goto delete; goto delete;
sum = del.br_startblock + del.br_blockcount; mod = xfs_rtb_to_rtxoff(mp,
div_u64_rem(sum, mp->m_sb.sb_rextsize, &mod); del.br_startblock + del.br_blockcount);
if (mod) { if (mod) {
/* /*
* Realtime extent not lined up at the end. * Realtime extent not lined up at the end.
...@@ -5432,7 +5414,8 @@ __xfs_bunmapi( ...@@ -5432,7 +5414,8 @@ __xfs_bunmapi(
goto error0; goto error0;
goto nodelete; 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) { if (mod) {
xfs_extlen_t off = mp->m_sb.sb_rextsize - mod; xfs_extlen_t off = mp->m_sb.sb_rextsize - mod;
...@@ -6209,7 +6192,7 @@ xfs_bmap_validate_extent( ...@@ -6209,7 +6192,7 @@ xfs_bmap_validate_extent(
return __this_address; return __this_address;
if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) { if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
if (!xfs_verify_rtext(mp, irec->br_startblock, if (!xfs_verify_rtbext(mp, irec->br_startblock,
irec->br_blockcount)) irec->br_blockcount))
return __this_address; return __this_address;
} else { } else {
......
...@@ -98,7 +98,7 @@ typedef struct xfs_sb { ...@@ -98,7 +98,7 @@ typedef struct xfs_sb {
uint32_t sb_blocksize; /* logical block size, bytes */ uint32_t sb_blocksize; /* logical block size, bytes */
xfs_rfsblock_t sb_dblocks; /* number of data blocks */ xfs_rfsblock_t sb_dblocks; /* number of data blocks */
xfs_rfsblock_t sb_rblocks; /* number of realtime 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 */ uuid_t sb_uuid; /* user-visible file system unique id */
xfs_fsblock_t sb_logstart; /* starting block of log if internal */ xfs_fsblock_t sb_logstart; /* starting block of log if internal */
xfs_ino_t sb_rootino; /* root inode number */ xfs_ino_t sb_rootino; /* root inode number */
...@@ -690,6 +690,22 @@ struct xfs_agfl { ...@@ -690,6 +690,22 @@ struct xfs_agfl {
ASSERT(xfs_daddr_to_agno(mp, d) == \ ASSERT(xfs_daddr_to_agno(mp, d) == \
xfs_daddr_to_agno(mp, (d) + (len) - 1))) 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 * XFS Timestamps
* ============== * ==============
...@@ -1142,24 +1158,10 @@ static inline bool xfs_dinode_has_large_extent_counts( ...@@ -1142,24 +1158,10 @@ static inline bool xfs_dinode_has_large_extent_counts(
#define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize) #define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize)
#define XFS_BLOCKMASK(mp) ((mp)->m_blockmask) #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_RTMIN(a,b) ((a) < (b) ? (a) : (b))
#define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b)) #define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b))
......
This diff is collapsed.
This diff is collapsed.
...@@ -975,6 +975,8 @@ xfs_sb_mount_common( ...@@ -975,6 +975,8 @@ xfs_sb_mount_common(
mp->m_blockmask = sbp->sb_blocksize - 1; mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1; 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[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); 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); ...@@ -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); 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, extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo,
int struct_version); int struct_version);
extern int xfs_sb_read_secondary(struct xfs_mount *mp, extern int xfs_sb_read_secondary(struct xfs_mount *mp,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_qm.h" #include "xfs_qm.h"
#include "xfs_trans_space.h" #include "xfs_trans_space.h"
#include "xfs_rtbitmap.h"
#define _ALLOC true #define _ALLOC true
#define _FREE false #define _FREE false
...@@ -217,11 +218,12 @@ xfs_rtalloc_block_count( ...@@ -217,11 +218,12 @@ xfs_rtalloc_block_count(
struct xfs_mount *mp, struct xfs_mount *mp,
unsigned int num_ops) unsigned int num_ops)
{ {
unsigned int blksz = XFS_FSB_TO_B(mp, 1); unsigned int rtbmp_blocks;
unsigned int rtbmp_bytes; xfs_rtxlen_t rtxlen;
rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY; rtxlen = xfs_extlen_to_rtxlen(mp, XFS_MAX_BMBT_EXTLEN);
return (howmany(rtbmp_bytes, blksz) + 1) * num_ops; rtbmp_blocks = xfs_rtbitmap_blockcount(mp, rtxlen);
return (rtbmp_blocks + 1) * num_ops;
} }
/* /*
......
...@@ -148,10 +148,10 @@ xfs_verify_rtbno( ...@@ -148,10 +148,10 @@ xfs_verify_rtbno(
/* Verify that a realtime device extent is fully contained inside the volume. */ /* Verify that a realtime device extent is fully contained inside the volume. */
bool bool
xfs_verify_rtext( xfs_verify_rtbext(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_rtblock_t rtbno, xfs_rtblock_t rtbno,
xfs_rtblock_t len) xfs_filblks_t len)
{ {
if (rtbno + len <= rtbno) if (rtbno + len <= rtbno)
return false; return false;
......
...@@ -11,6 +11,7 @@ typedef uint32_t prid_t; /* project ID */ ...@@ -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_agblock_t; /* blockno in alloc. group */
typedef uint32_t xfs_agino_t; /* inode # within allocation grp */ typedef uint32_t xfs_agino_t; /* inode # within allocation grp */
typedef uint32_t xfs_extlen_t; /* extent length in blocks */ 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 uint32_t xfs_agnumber_t; /* allocation group number */
typedef uint64_t xfs_extnum_t; /* # of extents in a file */ typedef uint64_t xfs_extnum_t; /* # of extents in a file */
typedef uint32_t xfs_aextnum_t; /* # extents in an attribute fork */ 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 */ ...@@ -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 uint64_t xfs_ufsize_t; /* unsigned bytes in a file */
typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */ 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 uint32_t xfs_rtword_t; /* word type for bitmap manipulations */
typedef int64_t xfs_lsn_t; /* log sequence number */ typedef int64_t xfs_lsn_t; /* log sequence number */
...@@ -31,6 +33,8 @@ typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ ...@@ -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_rtblock_t; /* extent (block) in realtime area */
typedef uint64_t xfs_fileoff_t; /* block number in a file */ 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_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 */ typedef int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */
...@@ -47,6 +51,7 @@ typedef void * xfs_failaddr_t; ...@@ -47,6 +51,7 @@ typedef void * xfs_failaddr_t;
#define NULLRFSBLOCK ((xfs_rfsblock_t)-1) #define NULLRFSBLOCK ((xfs_rfsblock_t)-1)
#define NULLRTBLOCK ((xfs_rtblock_t)-1) #define NULLRTBLOCK ((xfs_rtblock_t)-1)
#define NULLFILEOFF ((xfs_fileoff_t)-1) #define NULLFILEOFF ((xfs_fileoff_t)-1)
#define NULLRTEXTNO ((xfs_rtxnum_t)-1)
#define NULLAGBLOCK ((xfs_agblock_t)-1) #define NULLAGBLOCK ((xfs_agblock_t)-1)
#define NULLAGNUMBER ((xfs_agnumber_t)-1) #define NULLAGNUMBER ((xfs_agnumber_t)-1)
...@@ -145,6 +150,7 @@ typedef uint32_t xfs_dqid_t; ...@@ -145,6 +150,7 @@ typedef uint32_t xfs_dqid_t;
*/ */
#define XFS_NBBYLOG 3 /* log2(NBBY) */ #define XFS_NBBYLOG 3 /* log2(NBBY) */
#define XFS_WORDLOG 2 /* log2(sizeof(xfs_rtword_t)) */ #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_NBWORDLOG (XFS_NBBYLOG + XFS_WORDLOG)
#define XFS_NBWORD (1 << XFS_NBWORDLOG) #define XFS_NBWORD (1 << XFS_NBWORDLOG)
#define XFS_WORDMASK ((1 << XFS_WORDLOG) - 1) #define XFS_WORDMASK ((1 << XFS_WORDLOG) - 1)
...@@ -229,8 +235,8 @@ bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino); ...@@ -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_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_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_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
bool xfs_verify_rtext(struct xfs_mount *mp, xfs_rtblock_t rtbno, bool xfs_verify_rtbext(struct xfs_mount *mp, xfs_rtblock_t rtbno,
xfs_rtblock_t len); xfs_filblks_t len);
bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount); bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount);
bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off); bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off);
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min, void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
......
...@@ -410,7 +410,7 @@ xchk_bmap_iextent( ...@@ -410,7 +410,7 @@ xchk_bmap_iextent(
/* Make sure the extent points to a valid place. */ /* Make sure the extent points to a valid place. */
if (info->is_rt && 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, xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); irec->br_startoff);
if (!info->is_rt && if (!info->is_rt &&
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include "xfs_health.h" #include "xfs_health.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_icache.h" #include "xfs_icache.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_bmap_util.h" #include "xfs_bmap_util.h"
#include "xfs_rtbitmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
#include "scrub/common.h" #include "scrub/common.h"
#include "scrub/btree.h" #include "scrub/btree.h"
...@@ -225,7 +226,7 @@ xchk_inode_extsize( ...@@ -225,7 +226,7 @@ xchk_inode_extsize(
*/ */
if ((flags & XFS_DIFLAG_RTINHERIT) && if ((flags & XFS_DIFLAG_RTINHERIT) &&
(flags & XFS_DIFLAG_EXTSZINHERIT) && (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); xchk_ino_set_warning(sc, ino);
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
...@@ -48,12 +48,12 @@ xchk_rtbitmap_rec( ...@@ -48,12 +48,12 @@ xchk_rtbitmap_rec(
{ {
struct xfs_scrub *sc = priv; struct xfs_scrub *sc = priv;
xfs_rtblock_t startblock; xfs_rtblock_t startblock;
xfs_rtblock_t blockcount; xfs_filblks_t blockcount;
startblock = rec->ar_startext * mp->m_sb.sb_rextsize; startblock = xfs_rtx_to_rtb(mp, rec->ar_startext);
blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize; 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); xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
return 0; return 0;
} }
...@@ -128,26 +128,22 @@ xchk_rtbitmap( ...@@ -128,26 +128,22 @@ xchk_rtbitmap(
void void
xchk_xref_is_used_rt_space( xchk_xref_is_used_rt_space(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_rtblock_t fsbno, xfs_rtblock_t rtbno,
xfs_extlen_t len) xfs_extlen_t len)
{ {
xfs_rtblock_t startext; xfs_rtxnum_t startext;
xfs_rtblock_t endext; xfs_rtxnum_t endext;
xfs_rtblock_t extcount;
bool is_free; bool is_free;
int error; int error;
if (xchk_skip_xref(sc->sm)) if (xchk_skip_xref(sc->sm))
return; return;
startext = fsbno; startext = xfs_rtb_to_rtx(sc->mp, rtbno);
endext = fsbno + len - 1; endext = xfs_rtb_to_rtx(sc->mp, rtbno + len - 1);
do_div(startext, sc->mp->m_sb.sb_rextsize);
do_div(endext, sc->mp->m_sb.sb_rextsize);
extcount = endext - startext + 1;
xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount, error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext,
&is_free); endext - startext + 1, &is_free);
if (!xchk_should_check_xref(sc, &error, NULL)) if (!xchk_should_check_xref(sc, &error, NULL))
goto out_unlock; goto out_unlock;
if (is_free) if (is_free)
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
...@@ -81,34 +81,45 @@ typedef unsigned int xchk_rtsumoff_t; ...@@ -81,34 +81,45 @@ typedef unsigned int xchk_rtsumoff_t;
static inline int static inline int
xfsum_load( xfsum_load(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xchk_rtsumoff_t sumoff, xfs_rtsumoff_t sumoff,
xfs_suminfo_t *info) 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); sumoff << XFS_WORDLOG);
} }
static inline int static inline int
xfsum_store( xfsum_store(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xchk_rtsumoff_t sumoff, xfs_rtsumoff_t sumoff,
const xfs_suminfo_t info) 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); sumoff << XFS_WORDLOG);
} }
static inline int static inline int
xfsum_copyout( xfsum_copyout(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xchk_rtsumoff_t sumoff, xfs_rtsumoff_t sumoff,
xfs_suminfo_t *info, union xfs_suminfo_raw *rawinfo,
unsigned int nr_words) 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); 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. */ /* Update the summary file to reflect the free extent that we've accumulated. */
STATIC int STATIC int
xchk_rtsum_record_free( xchk_rtsum_record_free(
...@@ -121,23 +132,24 @@ xchk_rtsum_record_free( ...@@ -121,23 +132,24 @@ xchk_rtsum_record_free(
xfs_fileoff_t rbmoff; xfs_fileoff_t rbmoff;
xfs_rtblock_t rtbno; xfs_rtblock_t rtbno;
xfs_filblks_t rtlen; xfs_filblks_t rtlen;
xchk_rtsumoff_t offs; xfs_rtsumoff_t offs;
unsigned int lenlog; unsigned int lenlog;
xfs_suminfo_t v = 0; union xfs_suminfo_raw v;
xfs_suminfo_t value;
int error = 0; int error = 0;
if (xchk_should_terminate(sc, &error)) if (xchk_should_terminate(sc, &error))
return error; return error;
/* Compute the relevant location in the rtsum file. */ /* 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); 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; rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
rtlen = rec->ar_extcount * mp->m_sb.sb_rextsize; 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); xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino);
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
...@@ -147,9 +159,9 @@ xchk_rtsum_record_free( ...@@ -147,9 +159,9 @@ xchk_rtsum_record_free(
if (error) if (error)
return error; return error;
v++; value = xchk_rtsum_inc(sc->mp, &v);
trace_xchk_rtsum_record_free(mp, rec->ar_startext, rec->ar_extcount, trace_xchk_rtsum_record_free(mp, rec->ar_startext, rec->ar_extcount,
lenlog, offs, v); lenlog, offs, value);
return xfsum_store(sc, offs, v); return xfsum_store(sc, offs, v);
} }
...@@ -160,12 +172,11 @@ xchk_rtsum_compute( ...@@ -160,12 +172,11 @@ xchk_rtsum_compute(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_mount *mp = sc->mp; 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. */ /* If the bitmap size doesn't match the computed size, bail. */
rtbmp_bytes = howmany_64(mp->m_sb.sb_rextents, NBBY); rtbmp_blocks = xfs_rtbitmap_blockcount(mp, mp->m_sb.sb_rextents);
if (roundup_64(rtbmp_bytes, mp->m_sb.sb_blocksize) != if (XFS_FSB_TO_B(mp, rtbmp_blocks) != mp->m_rbmip->i_disk_size)
mp->m_rbmip->i_disk_size)
return -EFSCORRUPTED; return -EFSCORRUPTED;
return xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtsum_record_free, return xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtsum_record_free,
...@@ -177,14 +188,18 @@ STATIC int ...@@ -177,14 +188,18 @@ STATIC int
xchk_rtsum_compare( xchk_rtsum_compare(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_rtalloc_args args = {
.mp = sc->mp,
.tp = sc->tp,
};
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
struct xfs_buf *bp;
struct xfs_bmbt_irec map; struct xfs_bmbt_irec map;
xfs_fileoff_t off; xfs_fileoff_t off;
xchk_rtsumoff_t sumoff = 0; xchk_rtsumoff_t sumoff = 0;
int nmap; int nmap;
for (off = 0; off < XFS_B_TO_FSB(mp, mp->m_rsumsize); off++) { for (off = 0; off < XFS_B_TO_FSB(mp, mp->m_rsumsize); off++) {
union xfs_suminfo_raw *ondisk_info;
int error = 0; int error = 0;
if (xchk_should_terminate(sc, &error)) if (xchk_should_terminate(sc, &error))
...@@ -205,22 +220,23 @@ xchk_rtsum_compare( ...@@ -205,22 +220,23 @@ xchk_rtsum_compare(
} }
/* Read a block's worth of ondisk rtsummary file. */ /* 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)) if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
return error; return error;
/* Read a block's worth of computed rtsummary file. */ /* Read a block's worth of computed rtsummary file. */
error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize); error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize);
if (error) { if (error) {
xfs_trans_brelse(sc->tp, bp); xfs_rtbuf_cache_relse(&args);
return error; 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) mp->m_blockwsize << XFS_WORDLOG) != 0)
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off); xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
xfs_trans_brelse(sc->tp, bp); xfs_rtbuf_cache_relse(&args);
sumoff += mp->m_blockwsize; sumoff += mp->m_blockwsize;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_rtbitmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
#include "scrub/xfile.h" #include "scrub/xfile.h"
#include "scrub/xfarray.h" #include "scrub/xfarray.h"
......
...@@ -1036,17 +1036,18 @@ TRACE_EVENT(xfarray_sort_stats, ...@@ -1036,17 +1036,18 @@ TRACE_EVENT(xfarray_sort_stats,
#ifdef CONFIG_XFS_RT #ifdef CONFIG_XFS_RT
TRACE_EVENT(xchk_rtsum_record_free, TRACE_EVENT(xchk_rtsum_record_free,
TP_PROTO(struct xfs_mount *mp, xfs_rtblock_t start, TP_PROTO(struct xfs_mount *mp, xfs_rtxnum_t start,
uint64_t len, unsigned int log, loff_t pos, xfs_suminfo_t v), xfs_rtbxlen_t len, unsigned int log, loff_t pos,
TP_ARGS(mp, start, len, log, pos, v), xfs_suminfo_t value),
TP_ARGS(mp, start, len, log, pos, value),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(dev_t, dev) __field(dev_t, dev)
__field(dev_t, rtdev) __field(dev_t, rtdev)
__field(xfs_rtblock_t, start) __field(xfs_rtxnum_t, start)
__field(unsigned long long, len) __field(unsigned long long, len)
__field(unsigned int, log) __field(unsigned int, log)
__field(loff_t, pos) __field(loff_t, pos)
__field(xfs_suminfo_t, v) __field(xfs_suminfo_t, value)
), ),
TP_fast_assign( TP_fast_assign(
__entry->dev = mp->m_super->s_dev; __entry->dev = mp->m_super->s_dev;
...@@ -1055,7 +1056,7 @@ TRACE_EVENT(xchk_rtsum_record_free, ...@@ -1055,7 +1056,7 @@ TRACE_EVENT(xchk_rtsum_record_free,
__entry->len = len; __entry->len = len;
__entry->log = log; __entry->log = log;
__entry->pos = pos; __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", 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), MAJOR(__entry->dev), MINOR(__entry->dev),
...@@ -1064,7 +1065,7 @@ TRACE_EVENT(xchk_rtsum_record_free, ...@@ -1064,7 +1065,7 @@ TRACE_EVENT(xchk_rtsum_record_free,
__entry->len, __entry->len,
__entry->log, __entry->log,
__entry->pos, __entry->pos,
__entry->v) __entry->value)
); );
#endif /* CONFIG_XFS_RT */ #endif /* CONFIG_XFS_RT */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_iomap.h" #include "xfs_iomap.h"
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_rtbitmap.h"
/* Kernel only BMAP related definitions and functions */ /* Kernel only BMAP related definitions and functions */
...@@ -75,28 +76,28 @@ xfs_bmap_rtalloc( ...@@ -75,28 +76,28 @@ xfs_bmap_rtalloc(
{ {
struct xfs_mount *mp = ap->ip->i_mount; struct xfs_mount *mp = ap->ip->i_mount;
xfs_fileoff_t orig_offset = ap->offset; xfs_fileoff_t orig_offset = ap->offset;
xfs_rtblock_t rtb; xfs_rtxnum_t rtx;
xfs_extlen_t prod = 0; /* product factor for allocators */ xfs_rtxlen_t prod = 0; /* product factor for allocators */
xfs_extlen_t mod = 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 align; /* minimum allocation alignment */
xfs_extlen_t orig_length = ap->length; xfs_extlen_t orig_length = ap->length;
xfs_extlen_t minlen = mp->m_sb.sb_rextsize; xfs_extlen_t minlen = mp->m_sb.sb_rextsize;
xfs_extlen_t raminlen; xfs_rtxlen_t raminlen;
bool rtlocked = false; bool rtlocked = false;
bool ignore_locality = false; bool ignore_locality = false;
int error; int error;
align = xfs_get_extsz_hint(ap->ip); align = xfs_get_extsz_hint(ap->ip);
retry: 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, error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
align, 1, ap->eof, 0, align, 1, ap->eof, 0,
ap->conv, &ap->offset, &ap->length); ap->conv, &ap->offset, &ap->length);
if (error) if (error)
return error; return error;
ASSERT(ap->length); 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 * If we shifted the file offset downward to satisfy an extent size
...@@ -116,17 +117,14 @@ xfs_bmap_rtalloc( ...@@ -116,17 +117,14 @@ xfs_bmap_rtalloc(
prod = 1; prod = 1;
/* /*
* Set ralen to be the actual requested length in rtextents. * 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 * 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. * we rounded up to it, cut it back so it's valid again.
* Note that if it's a really large request (bigger than * 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 * XFS_BMBT_MAX_EXTLEN), we don't hear about that number, and can't
* adjust the starting point to match it. * adjust the starting point to match it.
*/ */
if (ralen * mp->m_sb.sb_rextsize >= XFS_MAX_BMBT_EXTLEN) ralen = xfs_extlen_to_rtxlen(mp, min(ap->length, XFS_MAX_BMBT_EXTLEN));
ralen = XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize;
/* /*
* Lock out modifications to both the RT bitmap and summary inodes * Lock out modifications to both the RT bitmap and summary inodes
...@@ -144,12 +142,10 @@ xfs_bmap_rtalloc( ...@@ -144,12 +142,10 @@ xfs_bmap_rtalloc(
* pick an extent that will space things out in the rt area. * pick an extent that will space things out in the rt area.
*/ */
if (ap->eof && ap->offset == 0) { if (ap->eof && ap->offset == 0) {
xfs_rtblock_t rtx; /* realtime extent no */
error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
if (error) if (error)
return error; return error;
ap->blkno = rtx * mp->m_sb.sb_rextsize; ap->blkno = xfs_rtx_to_rtb(mp, rtx);
} else { } else {
ap->blkno = 0; ap->blkno = 0;
} }
...@@ -160,20 +156,18 @@ xfs_bmap_rtalloc( ...@@ -160,20 +156,18 @@ xfs_bmap_rtalloc(
* Realtime allocation, done through xfs_rtallocate_extent. * Realtime allocation, done through xfs_rtallocate_extent.
*/ */
if (ignore_locality) if (ignore_locality)
ap->blkno = 0; rtx = 0;
else else
do_div(ap->blkno, mp->m_sb.sb_rextsize); rtx = xfs_rtb_to_rtx(mp, ap->blkno);
rtb = ap->blkno; raminlen = max_t(xfs_rtxlen_t, 1, xfs_extlen_to_rtxlen(mp, minlen));
ap->length = ralen; error = xfs_rtallocate_extent(ap->tp, rtx, raminlen, ralen, &ralen,
raminlen = max_t(xfs_extlen_t, 1, minlen / mp->m_sb.sb_rextsize); ap->wasdel, prod, &rtx);
error = xfs_rtallocate_extent(ap->tp, ap->blkno, raminlen, ap->length,
&ralen, ap->wasdel, prod, &rtb);
if (error) if (error)
return error; return error;
if (rtb != NULLRTBLOCK) { if (rtx != NULLRTEXTNO) {
ap->blkno = rtb * mp->m_sb.sb_rextsize; ap->blkno = xfs_rtx_to_rtb(mp, rtx);
ap->length = ralen * mp->m_sb.sb_rextsize; ap->length = xfs_rtxlen_to_extlen(mp, ralen);
ap->ip->i_nblocks += ap->length; ap->ip->i_nblocks += ap->length;
xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
if (ap->wasdel) if (ap->wasdel)
...@@ -690,7 +684,7 @@ xfs_can_free_eofblocks( ...@@ -690,7 +684,7 @@ xfs_can_free_eofblocks(
*/ */
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); 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) 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); last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
if (last_fsb <= end_fsb) if (last_fsb <= end_fsb)
return false; return false;
...@@ -780,12 +774,10 @@ xfs_alloc_file_space( ...@@ -780,12 +774,10 @@ xfs_alloc_file_space(
{ {
xfs_mount_t *mp = ip->i_mount; xfs_mount_t *mp = ip->i_mount;
xfs_off_t count; xfs_off_t count;
xfs_filblks_t allocated_fsb;
xfs_filblks_t allocatesize_fsb; xfs_filblks_t allocatesize_fsb;
xfs_extlen_t extsz, temp; xfs_extlen_t extsz, temp;
xfs_fileoff_t startoffset_fsb; xfs_fileoff_t startoffset_fsb;
xfs_fileoff_t endoffset_fsb; xfs_fileoff_t endoffset_fsb;
int nimaps;
int rt; int rt;
xfs_trans_t *tp; xfs_trans_t *tp;
xfs_bmbt_irec_t imaps[1], *imapp; xfs_bmbt_irec_t imaps[1], *imapp;
...@@ -808,7 +800,6 @@ xfs_alloc_file_space( ...@@ -808,7 +800,6 @@ xfs_alloc_file_space(
count = len; count = len;
imapp = &imaps[0]; imapp = &imaps[0];
nimaps = 1;
startoffset_fsb = XFS_B_TO_FSBT(mp, offset); startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
endoffset_fsb = XFS_B_TO_FSB(mp, offset + count); endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
allocatesize_fsb = endoffset_fsb - startoffset_fsb; allocatesize_fsb = endoffset_fsb - startoffset_fsb;
...@@ -819,6 +810,7 @@ xfs_alloc_file_space( ...@@ -819,6 +810,7 @@ xfs_alloc_file_space(
while (allocatesize_fsb && !error) { while (allocatesize_fsb && !error) {
xfs_fileoff_t s, e; xfs_fileoff_t s, e;
unsigned int dblocks, rblocks, resblks; unsigned int dblocks, rblocks, resblks;
int nimaps = 1;
/* /*
* Determine space reservations for data/realtime. * Determine space reservations for data/realtime.
...@@ -884,15 +876,19 @@ xfs_alloc_file_space( ...@@ -884,15 +876,19 @@ xfs_alloc_file_space(
if (error) if (error)
break; break;
allocated_fsb = imapp->br_blockcount; /*
* If the allocator cannot find a single free extent large
if (nimaps == 0) { * enough to cover the start block of the requested range,
error = -ENOSPC; * xfs_bmapi_write will return 0 but leave *nimaps set to 0.
break; *
* 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; return error;
...@@ -989,10 +985,8 @@ xfs_free_file_space( ...@@ -989,10 +985,8 @@ xfs_free_file_space(
/* We can only free complete realtime extents. */ /* We can only free complete realtime extents. */
if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) { if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) {
startoffset_fsb = roundup_64(startoffset_fsb, startoffset_fsb = xfs_rtb_roundup_rtx(mp, startoffset_fsb);
mp->m_sb.sb_rextsize); endoffset_fsb = xfs_rtb_rounddown_rtx(mp, endoffset_fsb);
endoffset_fsb = rounddown_64(endoffset_fsb,
mp->m_sb.sb_rextsize);
} }
/* /*
......
...@@ -214,6 +214,43 @@ xfs_ilock_iocb( ...@@ -214,6 +214,43 @@ xfs_ilock_iocb(
return 0; 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 STATIC ssize_t
xfs_file_dio_read( xfs_file_dio_read(
struct kiocb *iocb, struct kiocb *iocb,
...@@ -551,7 +588,7 @@ xfs_file_dio_write_aligned( ...@@ -551,7 +588,7 @@ xfs_file_dio_write_aligned(
unsigned int iolock = XFS_IOLOCK_SHARED; unsigned int iolock = XFS_IOLOCK_SHARED;
ssize_t ret; ssize_t ret;
ret = xfs_ilock_iocb(iocb, iolock); ret = xfs_ilock_iocb_for_write(iocb, &iolock);
if (ret) if (ret)
return ret; return ret;
ret = xfs_file_write_checks(iocb, from, &iolock); ret = xfs_file_write_checks(iocb, from, &iolock);
...@@ -618,7 +655,7 @@ xfs_file_dio_write_unaligned( ...@@ -618,7 +655,7 @@ xfs_file_dio_write_unaligned(
flags = IOMAP_DIO_FORCE_WAIT; flags = IOMAP_DIO_FORCE_WAIT;
} }
ret = xfs_ilock_iocb(iocb, iolock); ret = xfs_ilock_iocb_for_write(iocb, &iolock);
if (ret) if (ret)
return ret; return ret;
...@@ -1180,7 +1217,7 @@ xfs_file_remap_range( ...@@ -1180,7 +1217,7 @@ xfs_file_remap_range(
if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out)) if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out))
xfs_log_force_inode(dest); xfs_log_force_inode(dest);
out_unlock: out_unlock:
xfs_iunlock2_io_mmap(src, dest); xfs_iunlock2_remapping(src, dest);
if (ret) if (ret)
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
return remapped > 0 ? remapped : ret; return remapped > 0 ? remapped : ret;
...@@ -1328,6 +1365,7 @@ __xfs_filemap_fault( ...@@ -1328,6 +1365,7 @@ __xfs_filemap_fault(
struct inode *inode = file_inode(vmf->vma->vm_file); struct inode *inode = file_inode(vmf->vma->vm_file);
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
vm_fault_t ret; vm_fault_t ret;
unsigned int lock_mode = 0;
trace_xfs_filemap_fault(ip, order, write_fault); trace_xfs_filemap_fault(ip, order, write_fault);
...@@ -1336,24 +1374,23 @@ __xfs_filemap_fault( ...@@ -1336,24 +1374,23 @@ __xfs_filemap_fault(
file_update_time(vmf->vma->vm_file); 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)) { if (IS_DAX(inode)) {
pfn_t pfn; pfn_t pfn;
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
ret = xfs_dax_fault(vmf, order, write_fault, &pfn); ret = xfs_dax_fault(vmf, order, write_fault, &pfn);
if (ret & VM_FAULT_NEEDDSYNC) if (ret & VM_FAULT_NEEDDSYNC)
ret = dax_finish_sync_fault(vmf, order, pfn); ret = dax_finish_sync_fault(vmf, order, pfn);
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); } else if (write_fault) {
} else { ret = iomap_page_mkwrite(vmf, &xfs_page_mkwrite_iomap_ops);
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 { } else {
ret = filemap_fault(vmf); ret = filemap_fault(vmf);
} }
}
if (lock_mode)
xfs_iunlock(XFS_I(inode), lock_mode);
if (write_fault) if (write_fault)
sb_end_pagefault(inode->i_sb); sb_end_pagefault(inode->i_sb);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "xfs_refcount.h" #include "xfs_refcount.h"
#include "xfs_refcount_btree.h" #include "xfs_refcount_btree.h"
#include "xfs_alloc_btree.h" #include "xfs_alloc_btree.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_ag.h" #include "xfs_ag.h"
/* Convert an xfs_fsmap to an fsmap. */ /* Convert an xfs_fsmap to an fsmap. */
...@@ -483,11 +483,11 @@ xfs_getfsmap_rtdev_rtbitmap_helper( ...@@ -483,11 +483,11 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
xfs_rtblock_t rtbno; xfs_rtblock_t rtbno;
xfs_daddr_t rec_daddr, len_daddr; 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); rec_daddr = XFS_FSB_TO_BB(mp, rtbno);
irec.rm_startblock = 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); len_daddr = XFS_FSB_TO_BB(mp, rtbno);
irec.rm_blockcount = rtbno; irec.rm_blockcount = rtbno;
...@@ -514,7 +514,7 @@ xfs_getfsmap_rtdev_rtbitmap( ...@@ -514,7 +514,7 @@ xfs_getfsmap_rtdev_rtbitmap(
uint64_t eofs; uint64_t eofs;
int error; 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) if (keys[0].fmr_physical >= eofs)
return 0; return 0;
start_rtb = XFS_BB_TO_FSBT(mp, start_rtb = XFS_BB_TO_FSBT(mp,
...@@ -539,11 +539,8 @@ xfs_getfsmap_rtdev_rtbitmap( ...@@ -539,11 +539,8 @@ xfs_getfsmap_rtdev_rtbitmap(
* Set up query parameters to return free rtextents covering the range * Set up query parameters to return free rtextents covering the range
* we want. * we want.
*/ */
alow.ar_startext = start_rtb; alow.ar_startext = xfs_rtb_to_rtx(mp, start_rtb);
ahigh.ar_startext = end_rtb; ahigh.ar_startext = xfs_rtb_to_rtxup(mp, 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++;
error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh, error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
xfs_getfsmap_rtdev_rtbitmap_helper, info); xfs_getfsmap_rtdev_rtbitmap_helper, info);
if (error) if (error)
......
...@@ -918,6 +918,13 @@ xfs_droplink( ...@@ -918,6 +918,13 @@ xfs_droplink(
xfs_trans_t *tp, xfs_trans_t *tp,
xfs_inode_t *ip) 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); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
drop_nlink(VFS_I(ip)); drop_nlink(VFS_I(ip));
...@@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap( ...@@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap(
inode_unlock(VFS_I(ip1)); 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 * Reload the incore inode list for this inode. Caller should ensure that
* the link count cannot change, either by taking ILOCK_SHARED or otherwise * 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) ...@@ -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. */ /* Quotacheck is running but inode has not been added to quota counts. */
#define XFS_IQUOTAUNCHECKED (1 << 14) #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. */ /* All inode state flags related to inode reclaim. */
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \ #define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
XFS_IRECLAIM | \ XFS_IRECLAIM | \
...@@ -595,6 +603,7 @@ void xfs_end_io(struct work_struct *work); ...@@ -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); 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_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 static inline bool
xfs_inode_unlinked_incomplete( xfs_inode_unlinked_incomplete(
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "xfs_log.h" #include "xfs_log.h"
#include "xfs_log_priv.h" #include "xfs_log_priv.h"
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_rtbitmap.h"
#include <linux/iversion.h> #include <linux/iversion.h>
...@@ -107,7 +108,7 @@ xfs_inode_item_precommit( ...@@ -107,7 +108,7 @@ xfs_inode_item_precommit(
*/ */
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) && if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
(ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) && (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 | ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
XFS_DIFLAG_EXTSZINHERIT); XFS_DIFLAG_EXTSZINHERIT);
ip->i_extsize = 0; ip->i_extsize = 0;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_ioctl.h" #include "xfs_ioctl.h"
#include "xfs_xattr.h" #include "xfs_xattr.h"
#include "xfs_rtbitmap.h"
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/namei.h> #include <linux/namei.h>
...@@ -1004,7 +1005,7 @@ xfs_fill_fsxattr( ...@@ -1004,7 +1005,7 @@ xfs_fill_fsxattr(
* later. * later.
*/ */
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) && 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 | fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE |
FS_XFLAG_EXTSZINHERIT); FS_XFLAG_EXTSZINHERIT);
fa->fsx_extsize = 0; fa->fsx_extsize = 0;
...@@ -1130,7 +1131,7 @@ xfs_ioctl_setattr_xflags( ...@@ -1130,7 +1131,7 @@ xfs_ioctl_setattr_xflags(
/* If realtime flag is set then must have realtime device */ /* If realtime flag is set then must have realtime device */
if (fa->fsx_xflags & FS_XFLAG_REALTIME) { if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 || 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; return -EINVAL;
} }
......
...@@ -198,6 +198,18 @@ static inline uint64_t howmany_64(uint64_t x, uint32_t y) ...@@ -198,6 +198,18 @@ static inline uint64_t howmany_64(uint64_t x, uint32_t y)
return x; 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, int xfs_rw_bdev(struct block_device *bdev, sector_t sector, unsigned int count,
char *data, enum req_op op); char *data, enum req_op op);
......
...@@ -101,9 +101,9 @@ typedef struct xfs_mount { ...@@ -101,9 +101,9 @@ typedef struct xfs_mount {
/* /*
* Optional cache of rt summary level per bitmap block with the * Optional cache of rt summary level per bitmap block with the
* invariant that m_rsum_cache[bbno] <= the minimum i for which * invariant that m_rsum_cache[bbno] > the maximum i for which
* rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip * rsum[i][bbno] != 0, or 0 if rsum[i][bbno] == 0 for all i.
* inode lock. * Reads and writes are serialized by the rsumip inode lock.
*/ */
uint8_t *m_rsum_cache; uint8_t *m_rsum_cache;
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
...@@ -119,6 +119,7 @@ typedef struct xfs_mount { ...@@ -119,6 +119,7 @@ typedef struct xfs_mount {
uint8_t m_blkbb_log; /* blocklog - BBSHIFT */ uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
uint8_t m_agno_log; /* log #ag's */ uint8_t m_agno_log; /* log #ag's */
uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
int8_t m_rtxblklog; /* log2 of rextsize, if possible */
uint m_blockmask; /* sb_blocksize-1 */ uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */ uint m_blockwsize; /* sb_blocksize in words */
uint m_blockwmask; /* blockwsize-1 */ uint m_blockwmask; /* blockwsize-1 */
...@@ -152,6 +153,7 @@ typedef struct xfs_mount { ...@@ -152,6 +153,7 @@ typedef struct xfs_mount {
uint64_t m_features; /* active filesystem features */ uint64_t m_features; /* active filesystem features */
uint64_t m_low_space[XFS_LOWSP_MAX]; uint64_t m_low_space[XFS_LOWSP_MAX];
uint64_t m_low_rtexts[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_ino_geometry m_ino_geo; /* inode geometry */
struct xfs_trans_resv m_resv; /* precomputed res values */ struct xfs_trans_resv m_resv; /* precomputed res values */
/* low free space thresholds */ /* low free space thresholds */
......
...@@ -72,6 +72,10 @@ xfs_check_ondisk_structs(void) ...@@ -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_map_t, 4);
XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_local_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 * 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 * 4 bytes anyway so it's not obviously a problem. Hence for the moment
......
...@@ -1540,6 +1540,10 @@ xfs_reflink_remap_prep( ...@@ -1540,6 +1540,10 @@ xfs_reflink_remap_prep(
if (ret) if (ret)
goto out_unlock; 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; return 0;
out_unlock: out_unlock:
xfs_iunlock2_io_mmap(src, dest); xfs_iunlock2_io_mmap(src, dest);
......
This diff is collapsed.
...@@ -11,22 +11,6 @@ ...@@ -11,22 +11,6 @@
struct xfs_mount; struct xfs_mount;
struct xfs_trans; 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 #ifdef CONFIG_XFS_RT
/* /*
* Function prototypes for exported functions. * Function prototypes for exported functions.
...@@ -40,23 +24,14 @@ typedef int (*xfs_rtalloc_query_range_fn)( ...@@ -40,23 +24,14 @@ typedef int (*xfs_rtalloc_query_range_fn)(
int /* error */ int /* error */
xfs_rtallocate_extent( xfs_rtallocate_extent(
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_rtblock_t bno, /* starting block number to allocate */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t *len, /* out: actual length allocated */
int wasdel, /* was a delayed allocation extent */ int wasdel, /* was a delayed allocation extent */
xfs_extlen_t prod, /* extent product factor */ xfs_rtxlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock); /* out: start block allocated */ 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. * Initialize realtime fields in the mount structure.
...@@ -87,8 +62,8 @@ int /* error */ ...@@ -87,8 +62,8 @@ int /* error */
xfs_rtpick_extent( xfs_rtpick_extent(
struct xfs_mount *mp, /* file system mount point */ struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_extlen_t len, /* allocation length (rtextents) */ xfs_rtxlen_t len, /* allocation length (rtextents) */
xfs_rtblock_t *pick); /* result rt extent */ xfs_rtxnum_t *pick); /* result rt extent */
/* /*
* Grow the realtime area of the filesystem. * Grow the realtime area of the filesystem.
...@@ -98,54 +73,11 @@ xfs_growfs_rt( ...@@ -98,54 +73,11 @@ xfs_growfs_rt(
struct xfs_mount *mp, /* file system mount structure */ struct xfs_mount *mp, /* file system mount structure */
xfs_growfs_rt_t *in); /* user supplied growfs struct */ 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); int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp);
#else #else
# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (ENOSYS) # 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_rtpick_extent(m,t,l,rb) (ENOSYS) # define xfs_growfs_rt(mp,in) (-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_rtalloc_reinit_frextents(m) (0)
static inline int /* error */ static inline int /* error */
xfs_rtmount_init( xfs_rtmount_init(
...@@ -157,7 +89,7 @@ xfs_rtmount_init( ...@@ -157,7 +89,7 @@ xfs_rtmount_init(
xfs_warn(mp, "Not built with CONFIG_XFS_RT"); xfs_warn(mp, "Not built with CONFIG_XFS_RT");
return -ENOSYS; 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) # define xfs_rtunmount_inodes(m)
#endif /* CONFIG_XFS_RT */ #endif /* CONFIG_XFS_RT */
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "xfs_xattr.h" #include "xfs_xattr.h"
#include "xfs_iunlink_item.h" #include "xfs_iunlink_item.h"
#include "xfs_dahash_test.h" #include "xfs_dahash_test.h"
#include "xfs_rtbitmap.h"
#include "scrub/stats.h" #include "scrub/stats.h"
#include <linux/magic.h> #include <linux/magic.h>
...@@ -896,7 +897,7 @@ xfs_fs_statfs( ...@@ -896,7 +897,7 @@ xfs_fs_statfs(
statp->f_blocks = sbp->sb_rblocks; statp->f_blocks = sbp->sb_rblocks;
freertx = percpu_counter_sum_positive(&mp->m_frextents); 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; return 0;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "xfs_dquot_item.h" #include "xfs_dquot_item.h"
#include "xfs_dquot.h" #include "xfs_dquot.h"
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_rtbitmap.h"
struct kmem_cache *xfs_trans_cache; struct kmem_cache *xfs_trans_cache;
...@@ -655,6 +656,10 @@ xfs_trans_unreserve_and_mod_sb( ...@@ -655,6 +656,10 @@ xfs_trans_unreserve_and_mod_sb(
mp->m_sb.sb_agcount += tp->t_agcount_delta; mp->m_sb.sb_agcount += tp->t_agcount_delta;
mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta; mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta;
mp->m_sb.sb_rextsize += tp->t_rextsize_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_rbmblocks += tp->t_rbmblocks_delta;
mp->m_sb.sb_rblocks += tp->t_rblocks_delta; mp->m_sb.sb_rblocks += tp->t_rblocks_delta;
mp->m_sb.sb_rextents += tp->t_rextents_delta; mp->m_sb.sb_rextents += tp->t_rextents_delta;
...@@ -1196,7 +1201,7 @@ xfs_trans_alloc_inode( ...@@ -1196,7 +1201,7 @@ xfs_trans_alloc_inode(
retry: retry:
error = xfs_trans_alloc(mp, resv, dblocks, 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); force ? XFS_TRANS_RESERVE : 0, &tp);
if (error) if (error)
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment