Merge tag 'xfs-6.11-fixes-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Chandan Babu:

- Do not call out v1 inodes with non-zero di_nlink field as being
corrupt

- Change xfs_finobt_count_blocks() to count "free inode btree" blocks
rather than "inode btree" blocks

- Don't report the number of trimmed bytes via FITRIM because the
underlying storage isn't required to do anything and failed discard
IOs aren't reported to the caller anyway

- Fix incorrect setting of rm_owner field in an rmap query

- Report missing disk offset range in an fsmap query

- Obtain m_growlock when extending realtime section of the filesystem

- Reset rootdir extent size hint after extending realtime section of
the filesystem

* tag 'xfs-6.11-fixes-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: reset rootdir extent size hint after growfsrt
xfs: take m_growlock when running growfsrt
xfs: Fix missing interval for missing_owner in xfs fsmap
xfs: use XFS_BUF_DADDR_NULL for daddrs in getfsmap code
xfs: Fix the owner setting issue for rmap query in xfs fsmap
xfs: don't bother reporting blocks trimmed via FITRIM
xfs: xfs_finobt_count_blocks() walks the wrong btree
xfs: fix folio dirtying for XFILE_ALLOC callers
xfs: fix di_onlink checking for V1/V2 inodes

+114 -48
+1 -1
fs/xfs/libxfs/xfs_ialloc_btree.c
··· 749 if (error) 750 return error; 751 752 - cur = xfs_inobt_init_cursor(pag, tp, agbp); 753 error = xfs_btree_count_blocks(cur, tree_blocks); 754 xfs_btree_del_cursor(cur, error); 755 xfs_trans_brelse(tp, agbp);
··· 749 if (error) 750 return error; 751 752 + cur = xfs_finobt_init_cursor(pag, tp, agbp); 753 error = xfs_btree_count_blocks(cur, tree_blocks); 754 xfs_btree_del_cursor(cur, error); 755 xfs_trans_brelse(tp, agbp);
+10 -4
fs/xfs/libxfs/xfs_inode_buf.c
··· 514 return __this_address; 515 } 516 517 - if (dip->di_version > 1) { 518 if (dip->di_onlink) 519 - return __this_address; 520 - } else { 521 - if (dip->di_nlink) 522 return __this_address; 523 } 524
··· 514 return __this_address; 515 } 516 517 + /* 518 + * Historical note: xfsprogs in the 3.2 era set up its incore inodes to 519 + * have di_nlink track the link count, even if the actual filesystem 520 + * only supported V1 inodes (i.e. di_onlink). When writing out the 521 + * ondisk inode, it would set both the ondisk di_nlink and di_onlink to 522 + * the the incore di_nlink value, which is why we cannot check for 523 + * di_nlink==0 on a V1 inode. V2/3 inodes would get written out with 524 + * di_onlink==0, so we can check that. 525 + */ 526 + if (dip->di_version >= 2) { 527 if (dip->di_onlink) 528 return __this_address; 529 } 530
+1 -1
fs/xfs/scrub/xfile.c
··· 293 * (potentially last) reference in xfile_put_folio. 294 */ 295 if (flags & XFILE_ALLOC) 296 - folio_set_dirty(folio); 297 return folio; 298 } 299
··· 293 * (potentially last) reference in xfile_put_folio. 294 */ 295 if (flags & XFILE_ALLOC) 296 + folio_mark_dirty(folio); 297 return folio; 298 } 299
+11 -25
fs/xfs/xfs_discard.c
··· 158 xfs_trim_gather_extents( 159 struct xfs_perag *pag, 160 struct xfs_trim_cur *tcur, 161 - struct xfs_busy_extents *extents, 162 - uint64_t *blocks_trimmed) 163 { 164 struct xfs_mount *mp = pag->pag_mount; 165 struct xfs_trans *tp; ··· 279 280 xfs_extent_busy_insert_discard(pag, fbno, flen, 281 &extents->extent_list); 282 - *blocks_trimmed += flen; 283 next_extent: 284 if (tcur->by_bno) 285 error = xfs_btree_increment(cur, 0, &i); ··· 325 struct xfs_perag *pag, 326 xfs_agblock_t start, 327 xfs_agblock_t end, 328 - xfs_extlen_t minlen, 329 - uint64_t *blocks_trimmed) 330 { 331 struct xfs_trim_cur tcur = { 332 .start = start, ··· 351 extents->owner = extents; 352 INIT_LIST_HEAD(&extents->extent_list); 353 354 - error = xfs_trim_gather_extents(pag, &tcur, extents, 355 - blocks_trimmed); 356 if (error) { 357 kfree(extents); 358 break; ··· 385 struct xfs_mount *mp, 386 xfs_daddr_t start, 387 xfs_daddr_t end, 388 - xfs_extlen_t minlen, 389 - uint64_t *blocks_trimmed) 390 { 391 xfs_agnumber_t start_agno, end_agno; 392 xfs_agblock_t start_agbno, end_agbno; ··· 406 407 if (start_agno == end_agno) 408 agend = end_agbno; 409 - error = xfs_trim_perag_extents(pag, start_agbno, agend, minlen, 410 - blocks_trimmed); 411 if (error) 412 last_error = error; 413 ··· 424 struct xfs_trim_rtdev { 425 /* list of rt extents to free */ 426 struct list_head extent_list; 427 - 428 - /* pointer to count of blocks trimmed */ 429 - uint64_t *blocks_trimmed; 430 431 /* minimum length that caller allows us to trim */ 432 xfs_rtblock_t minlen_fsb; ··· 542 busyp->length = rlen; 543 INIT_LIST_HEAD(&busyp->list); 544 list_add_tail(&busyp->list, &tr->extent_list); 545 - *tr->blocks_trimmed += rlen; 546 547 tr->restart_rtx = rec->ar_startext + rec->ar_extcount; 548 return 0; ··· 552 struct xfs_mount *mp, 553 xfs_daddr_t start, 554 xfs_daddr_t end, 555 - xfs_daddr_t minlen, 556 - uint64_t *blocks_trimmed) 557 { 558 struct xfs_rtalloc_rec low = { }; 559 struct xfs_rtalloc_rec high = { }; 560 struct xfs_trim_rtdev tr = { 561 - .blocks_trimmed = blocks_trimmed, 562 .minlen_fsb = XFS_BB_TO_FSB(mp, minlen), 563 }; 564 struct xfs_trans *tp; ··· 622 return error; 623 } 624 #else 625 - # define xfs_trim_rtdev_extents(m,s,e,n,b) (-EOPNOTSUPP) 626 #endif /* CONFIG_XFS_RT */ 627 628 /* ··· 649 xfs_daddr_t start, end; 650 xfs_extlen_t minlen; 651 xfs_rfsblock_t max_blocks; 652 - uint64_t blocks_trimmed = 0; 653 int error, last_error = 0; 654 655 if (!capable(CAP_SYS_ADMIN)) ··· 693 end = start + BTOBBT(range.len) - 1; 694 695 if (bdev_max_discard_sectors(mp->m_ddev_targp->bt_bdev)) { 696 - error = xfs_trim_datadev_extents(mp, start, end, minlen, 697 - &blocks_trimmed); 698 if (error) 699 last_error = error; 700 } 701 702 if (rt_bdev && !xfs_trim_should_stop()) { 703 - error = xfs_trim_rtdev_extents(mp, start, end, minlen, 704 - &blocks_trimmed); 705 if (error) 706 last_error = error; 707 } ··· 707 if (last_error) 708 return last_error; 709 710 - range.len = XFS_FSB_TO_B(mp, blocks_trimmed); 711 if (copy_to_user(urange, &range, sizeof(range))) 712 return -EFAULT; 713 return 0;
··· 158 xfs_trim_gather_extents( 159 struct xfs_perag *pag, 160 struct xfs_trim_cur *tcur, 161 + struct xfs_busy_extents *extents) 162 { 163 struct xfs_mount *mp = pag->pag_mount; 164 struct xfs_trans *tp; ··· 280 281 xfs_extent_busy_insert_discard(pag, fbno, flen, 282 &extents->extent_list); 283 next_extent: 284 if (tcur->by_bno) 285 error = xfs_btree_increment(cur, 0, &i); ··· 327 struct xfs_perag *pag, 328 xfs_agblock_t start, 329 xfs_agblock_t end, 330 + xfs_extlen_t minlen) 331 { 332 struct xfs_trim_cur tcur = { 333 .start = start, ··· 354 extents->owner = extents; 355 INIT_LIST_HEAD(&extents->extent_list); 356 357 + error = xfs_trim_gather_extents(pag, &tcur, extents); 358 if (error) { 359 kfree(extents); 360 break; ··· 389 struct xfs_mount *mp, 390 xfs_daddr_t start, 391 xfs_daddr_t end, 392 + xfs_extlen_t minlen) 393 { 394 xfs_agnumber_t start_agno, end_agno; 395 xfs_agblock_t start_agbno, end_agbno; ··· 411 412 if (start_agno == end_agno) 413 agend = end_agbno; 414 + error = xfs_trim_perag_extents(pag, start_agbno, agend, minlen); 415 if (error) 416 last_error = error; 417 ··· 430 struct xfs_trim_rtdev { 431 /* list of rt extents to free */ 432 struct list_head extent_list; 433 434 /* minimum length that caller allows us to trim */ 435 xfs_rtblock_t minlen_fsb; ··· 551 busyp->length = rlen; 552 INIT_LIST_HEAD(&busyp->list); 553 list_add_tail(&busyp->list, &tr->extent_list); 554 555 tr->restart_rtx = rec->ar_startext + rec->ar_extcount; 556 return 0; ··· 562 struct xfs_mount *mp, 563 xfs_daddr_t start, 564 xfs_daddr_t end, 565 + xfs_daddr_t minlen) 566 { 567 struct xfs_rtalloc_rec low = { }; 568 struct xfs_rtalloc_rec high = { }; 569 struct xfs_trim_rtdev tr = { 570 .minlen_fsb = XFS_BB_TO_FSB(mp, minlen), 571 }; 572 struct xfs_trans *tp; ··· 634 return error; 635 } 636 #else 637 + # define xfs_trim_rtdev_extents(...) (-EOPNOTSUPP) 638 #endif /* CONFIG_XFS_RT */ 639 640 /* ··· 661 xfs_daddr_t start, end; 662 xfs_extlen_t minlen; 663 xfs_rfsblock_t max_blocks; 664 int error, last_error = 0; 665 666 if (!capable(CAP_SYS_ADMIN)) ··· 706 end = start + BTOBBT(range.len) - 1; 707 708 if (bdev_max_discard_sectors(mp->m_ddev_targp->bt_bdev)) { 709 + error = xfs_trim_datadev_extents(mp, start, end, minlen); 710 if (error) 711 last_error = error; 712 } 713 714 if (rt_bdev && !xfs_trim_should_stop()) { 715 + error = xfs_trim_rtdev_extents(mp, start, end, minlen); 716 if (error) 717 last_error = error; 718 } ··· 722 if (last_error) 723 return last_error; 724 725 + range.len = min_t(unsigned long long, range.len, 726 + XFS_FSB_TO_B(mp, max_blocks)); 727 if (copy_to_user(urange, &range, sizeof(range))) 728 return -EFAULT; 729 return 0;
+26 -4
fs/xfs/xfs_fsmap.c
··· 71 switch (src->fmr_owner) { 72 case 0: /* "lowest owner id possible" */ 73 case -1ULL: /* "highest owner id possible" */ 74 - dest->rm_owner = 0; 75 break; 76 case XFS_FMR_OWN_FREE: 77 dest->rm_owner = XFS_RMAP_OWN_NULL; ··· 162 xfs_daddr_t next_daddr; /* next daddr we expect */ 163 /* daddr of low fsmap key when we're using the rtbitmap */ 164 xfs_daddr_t low_daddr; 165 u64 missing_owner; /* owner of holes */ 166 u32 dev; /* device id */ 167 /* ··· 183 int (*fn)(struct xfs_trans *tp, 184 const struct xfs_fsmap *keys, 185 struct xfs_getfsmap_info *info); 186 }; 187 188 /* Compare two getfsmap device handlers. */ ··· 254 const struct xfs_rmap_irec *rec, 255 xfs_daddr_t rec_daddr) 256 { 257 - if (info->low_daddr != -1ULL) 258 return rec_daddr < info->low_daddr; 259 if (info->low.rm_blockcount) 260 return xfs_rmap_compare(rec, &info->low) < 0; ··· 295 info->next_daddr = rec_daddr; 296 return 0; 297 } 298 299 /* Are we just counting mappings? */ 300 if (info->head->fmh_count == 0) { ··· 918 919 /* Set up our device handlers. */ 920 memset(handlers, 0, sizeof(handlers)); 921 handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev); 922 if (use_rmap) 923 handlers[0].fn = xfs_getfsmap_datadev_rmapbt; 924 else 925 handlers[0].fn = xfs_getfsmap_datadev_bnobt; 926 if (mp->m_logdev_targp != mp->m_ddev_targp) { 927 handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev); 928 handlers[1].fn = xfs_getfsmap_logdev; 929 } 930 #ifdef CONFIG_XFS_RT 931 if (mp->m_rtdev_targp) { 932 handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev); 933 handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap; 934 } ··· 964 965 info.next_daddr = head->fmh_keys[0].fmr_physical + 966 head->fmh_keys[0].fmr_length; 967 info.fsmap_recs = fsmap_recs; 968 info.head = head; 969 ··· 985 * low key, zero out the low key so that we get 986 * everything from the beginning. 987 */ 988 - if (handlers[i].dev == head->fmh_keys[1].fmr_device) 989 dkeys[1] = head->fmh_keys[1]; 990 if (handlers[i].dev > head->fmh_keys[0].fmr_device) 991 memset(&dkeys[0], 0, sizeof(struct xfs_fsmap)); 992 ··· 1005 info.dev = handlers[i].dev; 1006 info.last = false; 1007 info.pag = NULL; 1008 - info.low_daddr = -1ULL; 1009 info.low.rm_blockcount = 0; 1010 error = handlers[i].fn(tp, dkeys, &info); 1011 if (error)
··· 71 switch (src->fmr_owner) { 72 case 0: /* "lowest owner id possible" */ 73 case -1ULL: /* "highest owner id possible" */ 74 + dest->rm_owner = src->fmr_owner; 75 break; 76 case XFS_FMR_OWN_FREE: 77 dest->rm_owner = XFS_RMAP_OWN_NULL; ··· 162 xfs_daddr_t next_daddr; /* next daddr we expect */ 163 /* daddr of low fsmap key when we're using the rtbitmap */ 164 xfs_daddr_t low_daddr; 165 + xfs_daddr_t end_daddr; /* daddr of high fsmap key */ 166 u64 missing_owner; /* owner of holes */ 167 u32 dev; /* device id */ 168 /* ··· 182 int (*fn)(struct xfs_trans *tp, 183 const struct xfs_fsmap *keys, 184 struct xfs_getfsmap_info *info); 185 + sector_t nr_sectors; 186 }; 187 188 /* Compare two getfsmap device handlers. */ ··· 252 const struct xfs_rmap_irec *rec, 253 xfs_daddr_t rec_daddr) 254 { 255 + if (info->low_daddr != XFS_BUF_DADDR_NULL) 256 return rec_daddr < info->low_daddr; 257 if (info->low.rm_blockcount) 258 return xfs_rmap_compare(rec, &info->low) < 0; ··· 293 info->next_daddr = rec_daddr; 294 return 0; 295 } 296 + 297 + /* 298 + * For an info->last query, we're looking for a gap between the last 299 + * mapping emitted and the high key specified by userspace. If the 300 + * user's query spans less than 1 fsblock, then info->high and 301 + * info->low will have the same rm_startblock, which causes rec_daddr 302 + * and next_daddr to be the same. Therefore, use the end_daddr that 303 + * we calculated from userspace's high key to synthesize the record. 304 + * Note that if the btree query found a mapping, there won't be a gap. 305 + */ 306 + if (info->last && info->end_daddr != XFS_BUF_DADDR_NULL) 307 + rec_daddr = info->end_daddr; 308 309 /* Are we just counting mappings? */ 310 if (info->head->fmh_count == 0) { ··· 904 905 /* Set up our device handlers. */ 906 memset(handlers, 0, sizeof(handlers)); 907 + handlers[0].nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); 908 handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev); 909 if (use_rmap) 910 handlers[0].fn = xfs_getfsmap_datadev_rmapbt; 911 else 912 handlers[0].fn = xfs_getfsmap_datadev_bnobt; 913 if (mp->m_logdev_targp != mp->m_ddev_targp) { 914 + handlers[1].nr_sectors = XFS_FSB_TO_BB(mp, 915 + mp->m_sb.sb_logblocks); 916 handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev); 917 handlers[1].fn = xfs_getfsmap_logdev; 918 } 919 #ifdef CONFIG_XFS_RT 920 if (mp->m_rtdev_targp) { 921 + handlers[2].nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); 922 handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev); 923 handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap; 924 } ··· 946 947 info.next_daddr = head->fmh_keys[0].fmr_physical + 948 head->fmh_keys[0].fmr_length; 949 + info.end_daddr = XFS_BUF_DADDR_NULL; 950 info.fsmap_recs = fsmap_recs; 951 info.head = head; 952 ··· 966 * low key, zero out the low key so that we get 967 * everything from the beginning. 968 */ 969 + if (handlers[i].dev == head->fmh_keys[1].fmr_device) { 970 dkeys[1] = head->fmh_keys[1]; 971 + info.end_daddr = min(handlers[i].nr_sectors - 1, 972 + dkeys[1].fmr_physical); 973 + } 974 if (handlers[i].dev > head->fmh_keys[0].fmr_device) 975 memset(&dkeys[0], 0, sizeof(struct xfs_fsmap)); 976 ··· 983 info.dev = handlers[i].dev; 984 info.last = false; 985 info.pag = NULL; 986 + info.low_daddr = XFS_BUF_DADDR_NULL; 987 info.low.rm_blockcount = 0; 988 error = handlers[i].fn(tp, dkeys, &info); 989 if (error)
+65 -13
fs/xfs/xfs_rtalloc.c
··· 785 } 786 787 /* 788 * Visible (exported) functions. 789 */ 790 ··· 845 xfs_extlen_t rsumblocks; /* current number of rt summary blks */ 846 xfs_sb_t *sbp; /* old superblock */ 847 uint8_t *rsum_cache; /* old summary cache */ 848 849 sbp = &mp->m_sb; 850 ··· 855 /* Needs to have been mounted with an rt device. */ 856 if (!XFS_IS_REALTIME_MOUNT(mp)) 857 return -EINVAL; 858 /* 859 * Mount should fail if the rt bitmap/summary files don't load, but 860 * we'll check anyway. 861 */ 862 if (!mp->m_rbmip || !mp->m_rsumip) 863 - return -EINVAL; 864 865 /* Shrink not supported. */ 866 if (in->newblocks <= sbp->sb_rblocks) 867 - return -EINVAL; 868 869 /* Can only change rt extent size when adding rt volume. */ 870 if (sbp->sb_rblocks > 0 && in->extsize != sbp->sb_rextsize) 871 - return -EINVAL; 872 873 /* Range check the extent size. */ 874 if (XFS_FSB_TO_B(mp, in->extsize) > XFS_MAX_RTEXTSIZE || 875 XFS_FSB_TO_B(mp, in->extsize) < XFS_MIN_RTEXTSIZE) 876 - return -EINVAL; 877 878 /* Unsupported realtime features. */ 879 if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp) || xfs_has_quota(mp)) 880 - return -EOPNOTSUPP; 881 882 nrblocks = in->newblocks; 883 error = xfs_sb_validate_fsb_count(sbp, nrblocks); 884 if (error) 885 - return error; 886 /* 887 * Read in the last block of the device, make sure it exists. 888 */ ··· 895 XFS_FSB_TO_BB(mp, nrblocks - 1), 896 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL); 897 if (error) 898 - return error; 899 xfs_buf_relse(bp); 900 901 /* ··· 903 */ 904 nrextents = nrblocks; 905 do_div(nrextents, in->extsize); 906 - if (!xfs_validate_rtextents(nrextents)) 907 - return -EINVAL; 908 nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents); 909 nrextslog = xfs_compute_rextslog(nrextents); 910 nrsumlevels = nrextslog + 1; ··· 917 * the log. This prevents us from getting a log overflow, 918 * since we'll log basically the whole summary file at once. 919 */ 920 - if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1)) 921 - return -EINVAL; 922 /* 923 * Get the old block counts for bitmap and summary inodes. 924 * These can't change since other growfs callers are locked out. ··· 933 */ 934 error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip); 935 if (error) 936 - return error; 937 error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); 938 if (error) 939 - return error; 940 941 rsum_cache = mp->m_rsum_cache; 942 if (nrbmblocks != sbp->sb_rbmblocks) ··· 1080 if (error) 1081 goto out_free; 1082 1083 /* Update secondary superblocks now the physical grow has completed */ 1084 error = xfs_update_secondary_sbs(mp); 1085 ··· 1109 } 1110 } 1111 1112 return error; 1113 } 1114
··· 785 } 786 787 /* 788 + * If we changed the rt extent size (meaning there was no rt volume previously) 789 + * and the root directory had EXTSZINHERIT and RTINHERIT set, it's possible 790 + * that the extent size hint on the root directory is no longer congruent with 791 + * the new rt extent size. Log the rootdir inode to fix this. 792 + */ 793 + static int 794 + xfs_growfs_rt_fixup_extsize( 795 + struct xfs_mount *mp) 796 + { 797 + struct xfs_inode *ip = mp->m_rootip; 798 + struct xfs_trans *tp; 799 + int error = 0; 800 + 801 + xfs_ilock(ip, XFS_IOLOCK_EXCL); 802 + if (!(ip->i_diflags & XFS_DIFLAG_RTINHERIT) || 803 + !(ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT)) 804 + goto out_iolock; 805 + 806 + error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange, 0, 0, false, 807 + &tp); 808 + if (error) 809 + goto out_iolock; 810 + 811 + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 812 + error = xfs_trans_commit(tp); 813 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 814 + 815 + out_iolock: 816 + xfs_iunlock(ip, XFS_IOLOCK_EXCL); 817 + return error; 818 + } 819 + 820 + /* 821 * Visible (exported) functions. 822 */ 823 ··· 812 xfs_extlen_t rsumblocks; /* current number of rt summary blks */ 813 xfs_sb_t *sbp; /* old superblock */ 814 uint8_t *rsum_cache; /* old summary cache */ 815 + xfs_agblock_t old_rextsize = mp->m_sb.sb_rextsize; 816 817 sbp = &mp->m_sb; 818 ··· 821 /* Needs to have been mounted with an rt device. */ 822 if (!XFS_IS_REALTIME_MOUNT(mp)) 823 return -EINVAL; 824 + 825 + if (!mutex_trylock(&mp->m_growlock)) 826 + return -EWOULDBLOCK; 827 /* 828 * Mount should fail if the rt bitmap/summary files don't load, but 829 * we'll check anyway. 830 */ 831 + error = -EINVAL; 832 if (!mp->m_rbmip || !mp->m_rsumip) 833 + goto out_unlock; 834 835 /* Shrink not supported. */ 836 if (in->newblocks <= sbp->sb_rblocks) 837 + goto out_unlock; 838 839 /* Can only change rt extent size when adding rt volume. */ 840 if (sbp->sb_rblocks > 0 && in->extsize != sbp->sb_rextsize) 841 + goto out_unlock; 842 843 /* Range check the extent size. */ 844 if (XFS_FSB_TO_B(mp, in->extsize) > XFS_MAX_RTEXTSIZE || 845 XFS_FSB_TO_B(mp, in->extsize) < XFS_MIN_RTEXTSIZE) 846 + goto out_unlock; 847 848 /* Unsupported realtime features. */ 849 + error = -EOPNOTSUPP; 850 if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp) || xfs_has_quota(mp)) 851 + goto out_unlock; 852 853 nrblocks = in->newblocks; 854 error = xfs_sb_validate_fsb_count(sbp, nrblocks); 855 if (error) 856 + goto out_unlock; 857 /* 858 * Read in the last block of the device, make sure it exists. 859 */ ··· 856 XFS_FSB_TO_BB(mp, nrblocks - 1), 857 XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL); 858 if (error) 859 + goto out_unlock; 860 xfs_buf_relse(bp); 861 862 /* ··· 864 */ 865 nrextents = nrblocks; 866 do_div(nrextents, in->extsize); 867 + if (!xfs_validate_rtextents(nrextents)) { 868 + error = -EINVAL; 869 + goto out_unlock; 870 + } 871 nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents); 872 nrextslog = xfs_compute_rextslog(nrextents); 873 nrsumlevels = nrextslog + 1; ··· 876 * the log. This prevents us from getting a log overflow, 877 * since we'll log basically the whole summary file at once. 878 */ 879 + if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1)) { 880 + error = -EINVAL; 881 + goto out_unlock; 882 + } 883 + 884 /* 885 * Get the old block counts for bitmap and summary inodes. 886 * These can't change since other growfs callers are locked out. ··· 889 */ 890 error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip); 891 if (error) 892 + goto out_unlock; 893 error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); 894 if (error) 895 + goto out_unlock; 896 897 rsum_cache = mp->m_rsum_cache; 898 if (nrbmblocks != sbp->sb_rbmblocks) ··· 1036 if (error) 1037 goto out_free; 1038 1039 + if (old_rextsize != in->extsize) { 1040 + error = xfs_growfs_rt_fixup_extsize(mp); 1041 + if (error) 1042 + goto out_free; 1043 + } 1044 + 1045 /* Update secondary superblocks now the physical grow has completed */ 1046 error = xfs_update_secondary_sbs(mp); 1047 ··· 1059 } 1060 } 1061 1062 + out_unlock: 1063 + mutex_unlock(&mp->m_growlock); 1064 return error; 1065 } 1066