Skip to content

Commit

Permalink
xfs: replace do_mod with native operations
Browse files Browse the repository at this point in the history
do_mod() is a hold-over from when we have different sizes for file
offsets and and other internal values for 40 bit XFS filesystems.
Hence depending on build flags variables passed to do_mod() could
change size. We no longer support those small format filesystems and
hence everything is of fixed size theses days, even on 32 bit
platforms.

As such, we can convert all the do_mod() callers to platform
optimised modulus operations as defined by linux/math64.h.
Individual conversions depend on the types of variables being used.

Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
  • Loading branch information
Dave Chinner authored and Darrick J. Wong committed Jun 8, 2018
1 parent bb3d48d commit 0703a8e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 50 deletions.
37 changes: 23 additions & 14 deletions fs/xfs/libxfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2923,7 +2923,7 @@ xfs_bmap_extsize_align(
* perform this alignment, or if a truncate shot us in the
* foot.
*/
temp = do_mod(orig_off, extsz);
div_u64_rem(orig_off, extsz, &temp);
if (temp) {
align_alen += temp;
align_off -= temp;
Expand Down Expand Up @@ -3497,15 +3497,17 @@ xfs_bmap_btalloc(
/* apply extent size hints if obtained earlier */
if (align) {
args.prod = align;
if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
args.mod = (xfs_extlen_t)(args.prod - args.mod);
div_u64_rem(ap->offset, args.prod, &args.mod);
if (args.mod)
args.mod = args.prod - args.mod;
} else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) {
args.prod = 1;
args.mod = 0;
} else {
args.prod = PAGE_SIZE >> mp->m_sb.sb_blocklog;
if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod))))
args.mod = (xfs_extlen_t)(args.prod - args.mod);
div_u64_rem(ap->offset, args.prod, &args.mod);
if (args.mod)
args.mod = args.prod - args.mod;
}
/*
* If we are not low on available data blocks, and the
Expand Down Expand Up @@ -4953,13 +4955,15 @@ xfs_bmap_del_extent_real(
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
xfs_fsblock_t bno;
xfs_filblks_t len;
xfs_extlen_t mod;

bno = div_u64_rem(del->br_startblock, mp->m_sb.sb_rextsize,
&mod);
ASSERT(mod == 0);
len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
&mod);
ASSERT(mod == 0);

ASSERT(do_mod(del->br_blockcount, mp->m_sb.sb_rextsize) == 0);
ASSERT(do_mod(del->br_startblock, mp->m_sb.sb_rextsize) == 0);
bno = del->br_startblock;
len = del->br_blockcount;
do_div(bno, mp->m_sb.sb_rextsize);
do_div(len, mp->m_sb.sb_rextsize);
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
if (error)
goto done;
Expand Down Expand Up @@ -5296,9 +5300,12 @@ __xfs_bunmapi(
del.br_blockcount = max_len;
}

if (!isrt)
goto delete;

sum = del.br_startblock + del.br_blockcount;
if (isrt &&
(mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
div_u64_rem(sum, mp->m_sb.sb_rextsize, &mod);
if (mod) {
/*
* Realtime extent not lined up at the end.
* The extent could have been split into written
Expand Down Expand Up @@ -5345,7 +5352,8 @@ __xfs_bunmapi(
goto error0;
goto nodelete;
}
if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
div_u64_rem(del.br_startblock, mp->m_sb.sb_rextsize, &mod);
if (mod) {
/*
* Realtime extent is lined up at the end but not
* at the front. We'll get rid of full extents if
Expand Down Expand Up @@ -5414,6 +5422,7 @@ __xfs_bunmapi(
}
}

delete:
if (wasdel) {
error = xfs_bmap_del_extent_delay(ip, whichfork, &icur,
&got, &del);
Expand Down
12 changes: 8 additions & 4 deletions fs/xfs/xfs_bmap_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ xfs_bmap_rtalloc(
int error; /* error return value */
xfs_mount_t *mp; /* mount point structure */
xfs_extlen_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_extlen_t align; /* minimum allocation alignment */
xfs_rtblock_t rtb;
Expand All @@ -99,7 +100,8 @@ xfs_bmap_rtalloc(
* If the offset & length are not perfectly aligned
* then kill prod, it will just get us in trouble.
*/
if (do_mod(ap->offset, align) || ap->length % align)
div_u64_rem(ap->offset, align, &mod);
if (mod || ap->length % align)
prod = 1;
/*
* Set ralen to be the actual requested length in rtextents.
Expand Down Expand Up @@ -936,9 +938,11 @@ xfs_alloc_file_space(
do_div(s, extsz);
s *= extsz;
e = startoffset_fsb + allocatesize_fsb;
if ((temp = do_mod(startoffset_fsb, extsz)))
div_u64_rem(startoffset_fsb, extsz, &temp);
if (temp)
e += temp;
if ((temp = do_mod(e, extsz)))
div_u64_rem(e, extsz, &temp);
if (temp)
e += extsz - temp;
} else {
s = 0;
Expand Down Expand Up @@ -1099,7 +1103,7 @@ xfs_adjust_extent_unmap_boundaries(

if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
mod = do_mod(imap.br_startblock, mp->m_sb.sb_rextsize);
div_u64_rem(imap.br_startblock, mp->m_sb.sb_rextsize, &mod);
if (mod)
*startoffset_fsb += mp->m_sb.sb_rextsize - mod;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2258,7 +2258,7 @@ xfs_ifree_cluster(
*/
ioffset = inum - xic->first_ino;
if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) {
ASSERT(do_mod(ioffset, inodes_per_cluster) == 0);
ASSERT(ioffset % inodes_per_cluster == 0);
continue;
}

Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/xfs_iomap.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ xfs_aligned_fsb_count(
if (extsz) {
xfs_extlen_t align;

align = do_mod(offset_fsb, extsz);
div_u64_rem(offset_fsb, extsz, &align);
if (align)
count_fsb += align;
align = do_mod(count_fsb, extsz);
div_u64_rem(count_fsb, extsz, &align);
if (align)
count_fsb += extsz - align;
}
Expand Down
19 changes: 0 additions & 19 deletions fs/xfs/xfs_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,25 +207,6 @@ static inline xfs_dev_t linux_to_xfs_dev_t(dev_t dev)
#define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL)
#define xfs_stack_trace() dump_stack()

/* Side effect free 64 bit mod operation */
static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
{
switch (n) {
case 4:
return *(__u32 *)a % b;
case 8:
{
__u64 c = *(__u64 *)a;
return do_div(c, b);
}
}

/* NOTREACHED */
return 0;
}

#define do_mod(a, b) xfs_do_mod(&(a), (b), sizeof(a))

static inline uint64_t roundup_64(uint64_t x, uint32_t y)
{
x += y - 1;
Expand Down
32 changes: 25 additions & 7 deletions fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,25 @@ xlog_verify_head(
be32_to_cpu((*rhead)->h_size));
}

/*
* We need to make sure we handle log wrapping properly, so we can't use the
* calculated logbno directly. Make sure it wraps to the correct bno inside the
* log.
*
* The log is limited to 32 bit sizes, so we use the appropriate modulus
* operation here and cast it back to a 64 bit daddr on return.
*/
static inline xfs_daddr_t
xlog_wrap_logbno(
struct xlog *log,
xfs_daddr_t bno)
{
int mod;

div_s64_rem(bno, log->l_logBBsize, &mod);
return mod;
}

/*
* Check whether the head of the log points to an unmount record. In other
* words, determine whether the log is clean. If so, update the in-core state
Expand Down Expand Up @@ -1283,12 +1302,13 @@ xlog_check_unmount_rec(
} else {
hblks = 1;
}
after_umount_blk = rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len));
after_umount_blk = do_mod(after_umount_blk, log->l_logBBsize);

after_umount_blk = xlog_wrap_logbno(log,
rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len)));

if (*head_blk == after_umount_blk &&
be32_to_cpu(rhead->h_num_logops) == 1) {
umount_data_blk = rhead_blk + hblks;
umount_data_blk = do_mod(umount_data_blk, log->l_logBBsize);
umount_data_blk = xlog_wrap_logbno(log, rhead_blk + hblks);
error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
if (error)
return error;
Expand Down Expand Up @@ -5459,9 +5479,7 @@ xlog_do_recovery_pass(
*/
if (blk_no + bblks <= log->l_logBBsize ||
blk_no >= log->l_logBBsize) {
/* mod blk_no in case the header wrapped and
* pushed it beyond the end of the log */
rblk_no = do_mod(blk_no, log->l_logBBsize);
rblk_no = xlog_wrap_logbno(log, blk_no);
error = xlog_bread(log, rblk_no, bblks, dbp,
&offset);
if (error)
Expand Down
10 changes: 7 additions & 3 deletions fs/xfs/xfs_rtalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,12 @@ xfs_rtallocate_extent_block(
/*
* If size should be a multiple of prod, make that so.
*/
if (prod > 1 && (p = do_mod(bestlen, prod)))
bestlen -= p;
if (prod > 1) {
div_u64_rem(bestlen, prod, &p);
if (p)
bestlen -= p;
}

/*
* Allocate besti for bestlen & return that.
*/
Expand Down Expand Up @@ -1263,7 +1267,7 @@ xfs_rtpick_extent(
b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
(log2 + 1);
if (b >= mp->m_sb.sb_rextents)
b = do_mod(b, mp->m_sb.sb_rextents);
div64_u64_rem(b, mp->m_sb.sb_rextents, &b);
if (b + len > mp->m_sb.sb_rextents)
b = mp->m_sb.sb_rextents - len;
}
Expand Down

0 comments on commit 0703a8e

Please sign in to comment.