Loading fs/xfs/libxfs/xfs_shared.h +1 −0 Original line number Diff line number Diff line Loading @@ -160,6 +160,7 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, #define XFS_TRANS_SB_RBLOCKS 0x00000800 #define XFS_TRANS_SB_REXTENTS 0x00001000 #define XFS_TRANS_SB_REXTSLOG 0x00002000 #define XFS_TRANS_SB_RGCOUNT 0x00004000 /* * Here we centralize the specification of XFS meta-data buffer reference count Loading fs/xfs/xfs_rtalloc.c +231 −35 Original line number Diff line number Diff line Loading @@ -766,6 +766,31 @@ xfs_growfs_rt_alloc_fake_mount( return nmp; } /* Free all the new space and return the number of extents actually freed. */ static int xfs_growfs_rt_free_new( struct xfs_rtgroup *rtg, struct xfs_rtalloc_args *nargs, xfs_rtbxlen_t *freed_rtx) { struct xfs_mount *mp = rtg_mount(rtg); xfs_rgnumber_t rgno = rtg_rgno(rtg); xfs_rtxnum_t start_rtx = 0, end_rtx; if (rgno < mp->m_sb.sb_rgcount) start_rtx = xfs_rtgroup_extents(mp, rgno); end_rtx = xfs_rtgroup_extents(nargs->mp, rgno); /* * Compute the first new extent that we want to free, being careful to * skip past a realtime superblock at the start of the realtime volume. */ if (xfs_has_rtsb(nargs->mp) && rgno == 0 && start_rtx == 0) start_rtx++; *freed_rtx = end_rtx - start_rtx; return xfs_rtfree_range(nargs, start_rtx, *freed_rtx); } static xfs_rfsblock_t xfs_growfs_rt_nrblocks( struct xfs_rtgroup *rtg, Loading @@ -786,6 +811,43 @@ xfs_growfs_rt_nrblocks( return min(nrblocks, step); } /* * If the post-grow filesystem will have an rtsb; we're initializing the first * rtgroup; and the filesystem didn't have a realtime section, write the rtsb * now, and attach the rtsb buffer to the real mount. */ static int xfs_growfs_rt_init_rtsb( const struct xfs_rtalloc_args *nargs, const struct xfs_rtgroup *rtg, const struct xfs_rtalloc_args *args) { struct xfs_mount *mp = args->mp; struct xfs_buf *rtsb_bp; int error; if (!xfs_has_rtsb(nargs->mp)) return 0; if (rtg_rgno(rtg) > 0) return 0; if (mp->m_sb.sb_rblocks) return 0; error = xfs_buf_get_uncached(mp->m_rtdev_targp, XFS_FSB_TO_BB(mp, 1), 0, &rtsb_bp); if (error) return error; rtsb_bp->b_maps[0].bm_bn = XFS_RTSB_DADDR; rtsb_bp->b_ops = &xfs_rtsb_buf_ops; xfs_update_rtsb(rtsb_bp, mp->m_sb_bp); mp->m_rtsb_bp = rtsb_bp; error = xfs_bwrite(rtsb_bp); xfs_buf_unlock(rtsb_bp); return error; } static int xfs_growfs_rt_bmblock( struct xfs_rtgroup *rtg, Loading @@ -808,7 +870,8 @@ xfs_growfs_rt_bmblock( int error; /* * Calculate new sb and mount fields for this round. * Calculate new sb and mount fields for this round. Also ensure the * rtg_extents value is uptodate as the rtbitmap code relies on it. */ nmp = nargs.mp = xfs_growfs_rt_alloc_fake_mount(mp, xfs_growfs_rt_nrblocks(rtg, nrblocks, rextsize, bmbno), Loading Loading @@ -861,6 +924,10 @@ xfs_growfs_rt_bmblock( goto out_cancel; } error = xfs_growfs_rt_init_rtsb(&nargs, rtg, &args); if (error) goto out_cancel; /* * Update superblock fields. */ Loading @@ -879,12 +946,14 @@ xfs_growfs_rt_bmblock( if (nmp->m_sb.sb_rextslog != mp->m_sb.sb_rextslog) xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTSLOG, nmp->m_sb.sb_rextslog - mp->m_sb.sb_rextslog); if (nmp->m_sb.sb_rgcount != mp->m_sb.sb_rgcount) xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_RGCOUNT, nmp->m_sb.sb_rgcount - mp->m_sb.sb_rgcount); /* * Free the new extent. */ freed_rtx = nmp->m_sb.sb_rextents - mp->m_sb.sb_rextents; error = xfs_rtfree_range(&nargs, mp->m_sb.sb_rextents, freed_rtx); error = xfs_growfs_rt_free_new(rtg, &nargs, &freed_rtx); xfs_rtbuf_cache_relse(&nargs); if (error) goto out_cancel; Loading Loading @@ -925,6 +994,15 @@ xfs_growfs_rt_bmblock( return error; } static xfs_rtxnum_t xfs_last_rtgroup_extents( struct xfs_mount *mp) { return mp->m_sb.sb_rextents - ((xfs_rtxnum_t)(mp->m_sb.sb_rgcount - 1) * mp->m_sb.sb_rgextents); } /* * Calculate the last rbmblock currently used. * Loading @@ -935,11 +1013,20 @@ xfs_last_rt_bmblock( struct xfs_rtgroup *rtg) { struct xfs_mount *mp = rtg_mount(rtg); xfs_fileoff_t bmbno = mp->m_sb.sb_rbmblocks; xfs_rgnumber_t rgno = rtg_rgno(rtg); xfs_fileoff_t bmbno = 0; ASSERT(!mp->m_sb.sb_rgcount || rgno >= mp->m_sb.sb_rgcount - 1); if (mp->m_sb.sb_rgcount && rgno == mp->m_sb.sb_rgcount - 1) { xfs_rtxnum_t nrext = xfs_last_rtgroup_extents(mp); /* Skip the current block if it is exactly full. */ if (xfs_rtx_to_rbmword(mp, mp->m_sb.sb_rextents) != 0) /* Also fill up the previous block if not entirely full. */ bmbno = xfs_rtbitmap_blockcount_len(mp, nrext); if (xfs_rtx_to_rbmword(mp, nrext) != 0) bmbno--; } return bmbno; } Loading @@ -956,38 +1043,56 @@ xfs_growfs_rt_alloc_blocks( struct xfs_mount *mp = rtg_mount(rtg); struct xfs_inode *rbmip = rtg->rtg_inodes[XFS_RTGI_BITMAP]; struct xfs_inode *rsumip = rtg->rtg_inodes[XFS_RTGI_SUMMARY]; xfs_extlen_t orbmblocks; xfs_extlen_t orsumblocks; xfs_extlen_t nrsumblocks; xfs_extlen_t orbmblocks = 0; xfs_extlen_t orsumblocks = 0; struct xfs_mount *nmp; int error; int error = 0; nmp = xfs_growfs_rt_alloc_fake_mount(mp, nrblocks, rextsize); if (!nmp) return -ENOMEM; *nrbmblocks = nmp->m_sb.sb_rbmblocks; if (xfs_has_rtgroups(mp)) { /* * For file systems with the rtgroups feature, the RT bitmap and * summary are always fully allocated, which means that we never * need to grow the existing files. * * But we have to be careful to only fill the bitmap until the * end of the actually used range. */ if (rtg_rgno(rtg) == nmp->m_sb.sb_rgcount - 1) *nrbmblocks = xfs_rtbitmap_blockcount_len(nmp, xfs_last_rtgroup_extents(nmp)); if (mp->m_sb.sb_rgcount && rtg_rgno(rtg) == mp->m_sb.sb_rgcount - 1) goto out_free; } else { /* * Get the old block counts for bitmap and summary inodes. * These can't change since other growfs callers are locked out. */ orbmblocks = XFS_B_TO_FSB(mp, rbmip->i_disk_size); orsumblocks = XFS_B_TO_FSB(mp, rsumip->i_disk_size); nmp = xfs_growfs_rt_alloc_fake_mount(mp, nrblocks, rextsize); if (!nmp) return -ENOMEM; *nrbmblocks = nmp->m_sb.sb_rbmblocks; nrsumblocks = nmp->m_rsumblocks; kfree(nmp); } error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_BITMAP, orbmblocks, *nrbmblocks, NULL); nmp->m_sb.sb_rbmblocks, NULL); if (error) goto out_free; error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_SUMMARY, orsumblocks, nmp->m_rsumblocks, NULL); out_free: kfree(nmp); return error; return xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_SUMMARY, orsumblocks, nrsumblocks, NULL); } static int xfs_growfs_rtg( struct xfs_mount *mp, xfs_rgnumber_t rgno, xfs_rfsblock_t nrblocks, xfs_agblock_t rextsize) { Loading @@ -998,7 +1103,7 @@ xfs_growfs_rtg( unsigned int i; int error; rtg = xfs_rtgroup_grab(mp, 0); rtg = xfs_rtgroup_grab(mp, rgno); if (!rtg) return -EINVAL; Loading Loading @@ -1069,14 +1174,67 @@ xfs_growfs_check_rtgeom( return error; } /* * Compute the new number of rt groups and ensure that /rtgroups exists. * * Changing the rtgroup size is not allowed (even if the rt volume hasn't yet * been initialized) because the userspace ABI doesn't support it. */ static int xfs_growfs_rt_prep_groups( struct xfs_mount *mp, xfs_rfsblock_t rblocks, xfs_extlen_t rextsize, xfs_rgnumber_t *new_rgcount) { int error; *new_rgcount = howmany_64(rblocks, mp->m_sb.sb_rgextents * rextsize); if (*new_rgcount > XFS_MAX_RGNUMBER) return -EINVAL; /* Make sure the /rtgroups dir has been created */ if (!mp->m_rtdirip) { struct xfs_trans *tp; error = xfs_trans_alloc_empty(mp, &tp); if (error) return error; error = xfs_rtginode_load_parent(tp); xfs_trans_cancel(tp); if (error == -ENOENT) error = xfs_rtginode_mkdir_parent(mp); if (error) return error; } return 0; } static bool xfs_grow_last_rtg( struct xfs_mount *mp) { if (!xfs_has_rtgroups(mp)) return true; if (mp->m_sb.sb_rgcount == 0) return false; return xfs_rtgroup_extents(mp, mp->m_sb.sb_rgcount - 1) <= mp->m_sb.sb_rgextents; } /* * Grow the realtime area of the filesystem. */ int xfs_growfs_rt( xfs_mount_t *mp, /* mount point for filesystem */ xfs_growfs_rt_t *in) /* growfs rt input struct */ struct xfs_mount *mp, struct xfs_growfs_rt *in) { xfs_rgnumber_t old_rgcount = mp->m_sb.sb_rgcount; xfs_rgnumber_t new_rgcount = 1; xfs_rgnumber_t rgno; struct xfs_buf *bp; xfs_agblock_t old_rextsize = mp->m_sb.sb_rextsize; int error; Loading Loading @@ -1134,18 +1292,56 @@ xfs_growfs_rt( if (error) goto out_unlock; error = xfs_growfs_rtg(mp, in->newblocks, in->extsize); if (xfs_has_rtgroups(mp)) { error = xfs_growfs_rt_prep_groups(mp, in->newblocks, in->extsize, &new_rgcount); if (error) goto out_unlock; } if (old_rextsize != in->extsize) { error = xfs_growfs_rt_fixup_extsize(mp); if (xfs_grow_last_rtg(mp)) { error = xfs_growfs_rtg(mp, old_rgcount - 1, in->newblocks, in->extsize); if (error) goto out_unlock; } /* Update secondary superblocks now the physical grow has completed */ error = xfs_update_secondary_sbs(mp); for (rgno = old_rgcount; rgno < new_rgcount; rgno++) { xfs_rtbxlen_t rextents = div_u64(in->newblocks, in->extsize); error = xfs_rtgroup_alloc(mp, rgno, new_rgcount, rextents); if (error) goto out_unlock; error = xfs_growfs_rtg(mp, rgno, in->newblocks, in->extsize); if (error) { struct xfs_rtgroup *rtg; rtg = xfs_rtgroup_grab(mp, rgno); if (!WARN_ON_ONCE(!rtg)) { xfs_rtunmount_rtg(rtg); xfs_rtgroup_rele(rtg); xfs_rtgroup_free(mp, rgno); } break; } } if (!error && old_rextsize != in->extsize) error = xfs_growfs_rt_fixup_extsize(mp); /* * Update secondary superblocks now the physical grow has completed. * * Also do this in case of an error as we might have already * successfully updated one or more RTGs and incremented sb_rgcount. */ if (!xfs_is_shutdown(mp)) { int error2 = xfs_update_secondary_sbs(mp); if (!error) error = error2; } out_unlock: mutex_unlock(&mp->m_growlock); Loading fs/xfs/xfs_trans.c +9 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,10 @@ xfs_trans_mod_sb( case XFS_TRANS_SB_REXTSLOG: tp->t_rextslog_delta += delta; break; case XFS_TRANS_SB_RGCOUNT: ASSERT(delta > 0); tp->t_rgcount_delta += delta; break; default: ASSERT(0); return; Loading Loading @@ -561,6 +565,10 @@ xfs_trans_apply_sb_deltas( sbp->sb_rextslog += tp->t_rextslog_delta; whole = 1; } if (tp->t_rgcount_delta) { be32_add_cpu(&sbp->sb_rgcount, tp->t_rgcount_delta); whole = 1; } xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); if (whole) Loading Loading @@ -674,6 +682,7 @@ xfs_trans_unreserve_and_mod_sb( mp->m_sb.sb_rblocks += tp->t_rblocks_delta; mp->m_sb.sb_rextents += tp->t_rextents_delta; mp->m_sb.sb_rextslog += tp->t_rextslog_delta; mp->m_sb.sb_rgcount += tp->t_rgcount_delta; spin_unlock(&mp->m_sb_lock); /* Loading fs/xfs/xfs_trans.h +1 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,7 @@ typedef struct xfs_trans { int64_t t_rblocks_delta;/* superblock rblocks change */ int64_t t_rextents_delta;/* superblocks rextents chg */ int64_t t_rextslog_delta;/* superblocks rextslog chg */ int64_t t_rgcount_delta; /* realtime group count */ struct list_head t_items; /* log item descriptors */ struct list_head t_busy; /* list of busy extents */ struct list_head t_dfops; /* deferred operations */ Loading Loading
fs/xfs/libxfs/xfs_shared.h +1 −0 Original line number Diff line number Diff line Loading @@ -160,6 +160,7 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, #define XFS_TRANS_SB_RBLOCKS 0x00000800 #define XFS_TRANS_SB_REXTENTS 0x00001000 #define XFS_TRANS_SB_REXTSLOG 0x00002000 #define XFS_TRANS_SB_RGCOUNT 0x00004000 /* * Here we centralize the specification of XFS meta-data buffer reference count Loading
fs/xfs/xfs_rtalloc.c +231 −35 Original line number Diff line number Diff line Loading @@ -766,6 +766,31 @@ xfs_growfs_rt_alloc_fake_mount( return nmp; } /* Free all the new space and return the number of extents actually freed. */ static int xfs_growfs_rt_free_new( struct xfs_rtgroup *rtg, struct xfs_rtalloc_args *nargs, xfs_rtbxlen_t *freed_rtx) { struct xfs_mount *mp = rtg_mount(rtg); xfs_rgnumber_t rgno = rtg_rgno(rtg); xfs_rtxnum_t start_rtx = 0, end_rtx; if (rgno < mp->m_sb.sb_rgcount) start_rtx = xfs_rtgroup_extents(mp, rgno); end_rtx = xfs_rtgroup_extents(nargs->mp, rgno); /* * Compute the first new extent that we want to free, being careful to * skip past a realtime superblock at the start of the realtime volume. */ if (xfs_has_rtsb(nargs->mp) && rgno == 0 && start_rtx == 0) start_rtx++; *freed_rtx = end_rtx - start_rtx; return xfs_rtfree_range(nargs, start_rtx, *freed_rtx); } static xfs_rfsblock_t xfs_growfs_rt_nrblocks( struct xfs_rtgroup *rtg, Loading @@ -786,6 +811,43 @@ xfs_growfs_rt_nrblocks( return min(nrblocks, step); } /* * If the post-grow filesystem will have an rtsb; we're initializing the first * rtgroup; and the filesystem didn't have a realtime section, write the rtsb * now, and attach the rtsb buffer to the real mount. */ static int xfs_growfs_rt_init_rtsb( const struct xfs_rtalloc_args *nargs, const struct xfs_rtgroup *rtg, const struct xfs_rtalloc_args *args) { struct xfs_mount *mp = args->mp; struct xfs_buf *rtsb_bp; int error; if (!xfs_has_rtsb(nargs->mp)) return 0; if (rtg_rgno(rtg) > 0) return 0; if (mp->m_sb.sb_rblocks) return 0; error = xfs_buf_get_uncached(mp->m_rtdev_targp, XFS_FSB_TO_BB(mp, 1), 0, &rtsb_bp); if (error) return error; rtsb_bp->b_maps[0].bm_bn = XFS_RTSB_DADDR; rtsb_bp->b_ops = &xfs_rtsb_buf_ops; xfs_update_rtsb(rtsb_bp, mp->m_sb_bp); mp->m_rtsb_bp = rtsb_bp; error = xfs_bwrite(rtsb_bp); xfs_buf_unlock(rtsb_bp); return error; } static int xfs_growfs_rt_bmblock( struct xfs_rtgroup *rtg, Loading @@ -808,7 +870,8 @@ xfs_growfs_rt_bmblock( int error; /* * Calculate new sb and mount fields for this round. * Calculate new sb and mount fields for this round. Also ensure the * rtg_extents value is uptodate as the rtbitmap code relies on it. */ nmp = nargs.mp = xfs_growfs_rt_alloc_fake_mount(mp, xfs_growfs_rt_nrblocks(rtg, nrblocks, rextsize, bmbno), Loading Loading @@ -861,6 +924,10 @@ xfs_growfs_rt_bmblock( goto out_cancel; } error = xfs_growfs_rt_init_rtsb(&nargs, rtg, &args); if (error) goto out_cancel; /* * Update superblock fields. */ Loading @@ -879,12 +946,14 @@ xfs_growfs_rt_bmblock( if (nmp->m_sb.sb_rextslog != mp->m_sb.sb_rextslog) xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_REXTSLOG, nmp->m_sb.sb_rextslog - mp->m_sb.sb_rextslog); if (nmp->m_sb.sb_rgcount != mp->m_sb.sb_rgcount) xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_RGCOUNT, nmp->m_sb.sb_rgcount - mp->m_sb.sb_rgcount); /* * Free the new extent. */ freed_rtx = nmp->m_sb.sb_rextents - mp->m_sb.sb_rextents; error = xfs_rtfree_range(&nargs, mp->m_sb.sb_rextents, freed_rtx); error = xfs_growfs_rt_free_new(rtg, &nargs, &freed_rtx); xfs_rtbuf_cache_relse(&nargs); if (error) goto out_cancel; Loading Loading @@ -925,6 +994,15 @@ xfs_growfs_rt_bmblock( return error; } static xfs_rtxnum_t xfs_last_rtgroup_extents( struct xfs_mount *mp) { return mp->m_sb.sb_rextents - ((xfs_rtxnum_t)(mp->m_sb.sb_rgcount - 1) * mp->m_sb.sb_rgextents); } /* * Calculate the last rbmblock currently used. * Loading @@ -935,11 +1013,20 @@ xfs_last_rt_bmblock( struct xfs_rtgroup *rtg) { struct xfs_mount *mp = rtg_mount(rtg); xfs_fileoff_t bmbno = mp->m_sb.sb_rbmblocks; xfs_rgnumber_t rgno = rtg_rgno(rtg); xfs_fileoff_t bmbno = 0; ASSERT(!mp->m_sb.sb_rgcount || rgno >= mp->m_sb.sb_rgcount - 1); if (mp->m_sb.sb_rgcount && rgno == mp->m_sb.sb_rgcount - 1) { xfs_rtxnum_t nrext = xfs_last_rtgroup_extents(mp); /* Skip the current block if it is exactly full. */ if (xfs_rtx_to_rbmword(mp, mp->m_sb.sb_rextents) != 0) /* Also fill up the previous block if not entirely full. */ bmbno = xfs_rtbitmap_blockcount_len(mp, nrext); if (xfs_rtx_to_rbmword(mp, nrext) != 0) bmbno--; } return bmbno; } Loading @@ -956,38 +1043,56 @@ xfs_growfs_rt_alloc_blocks( struct xfs_mount *mp = rtg_mount(rtg); struct xfs_inode *rbmip = rtg->rtg_inodes[XFS_RTGI_BITMAP]; struct xfs_inode *rsumip = rtg->rtg_inodes[XFS_RTGI_SUMMARY]; xfs_extlen_t orbmblocks; xfs_extlen_t orsumblocks; xfs_extlen_t nrsumblocks; xfs_extlen_t orbmblocks = 0; xfs_extlen_t orsumblocks = 0; struct xfs_mount *nmp; int error; int error = 0; nmp = xfs_growfs_rt_alloc_fake_mount(mp, nrblocks, rextsize); if (!nmp) return -ENOMEM; *nrbmblocks = nmp->m_sb.sb_rbmblocks; if (xfs_has_rtgroups(mp)) { /* * For file systems with the rtgroups feature, the RT bitmap and * summary are always fully allocated, which means that we never * need to grow the existing files. * * But we have to be careful to only fill the bitmap until the * end of the actually used range. */ if (rtg_rgno(rtg) == nmp->m_sb.sb_rgcount - 1) *nrbmblocks = xfs_rtbitmap_blockcount_len(nmp, xfs_last_rtgroup_extents(nmp)); if (mp->m_sb.sb_rgcount && rtg_rgno(rtg) == mp->m_sb.sb_rgcount - 1) goto out_free; } else { /* * Get the old block counts for bitmap and summary inodes. * These can't change since other growfs callers are locked out. */ orbmblocks = XFS_B_TO_FSB(mp, rbmip->i_disk_size); orsumblocks = XFS_B_TO_FSB(mp, rsumip->i_disk_size); nmp = xfs_growfs_rt_alloc_fake_mount(mp, nrblocks, rextsize); if (!nmp) return -ENOMEM; *nrbmblocks = nmp->m_sb.sb_rbmblocks; nrsumblocks = nmp->m_rsumblocks; kfree(nmp); } error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_BITMAP, orbmblocks, *nrbmblocks, NULL); nmp->m_sb.sb_rbmblocks, NULL); if (error) goto out_free; error = xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_SUMMARY, orsumblocks, nmp->m_rsumblocks, NULL); out_free: kfree(nmp); return error; return xfs_rtfile_initialize_blocks(rtg, XFS_RTGI_SUMMARY, orsumblocks, nrsumblocks, NULL); } static int xfs_growfs_rtg( struct xfs_mount *mp, xfs_rgnumber_t rgno, xfs_rfsblock_t nrblocks, xfs_agblock_t rextsize) { Loading @@ -998,7 +1103,7 @@ xfs_growfs_rtg( unsigned int i; int error; rtg = xfs_rtgroup_grab(mp, 0); rtg = xfs_rtgroup_grab(mp, rgno); if (!rtg) return -EINVAL; Loading Loading @@ -1069,14 +1174,67 @@ xfs_growfs_check_rtgeom( return error; } /* * Compute the new number of rt groups and ensure that /rtgroups exists. * * Changing the rtgroup size is not allowed (even if the rt volume hasn't yet * been initialized) because the userspace ABI doesn't support it. */ static int xfs_growfs_rt_prep_groups( struct xfs_mount *mp, xfs_rfsblock_t rblocks, xfs_extlen_t rextsize, xfs_rgnumber_t *new_rgcount) { int error; *new_rgcount = howmany_64(rblocks, mp->m_sb.sb_rgextents * rextsize); if (*new_rgcount > XFS_MAX_RGNUMBER) return -EINVAL; /* Make sure the /rtgroups dir has been created */ if (!mp->m_rtdirip) { struct xfs_trans *tp; error = xfs_trans_alloc_empty(mp, &tp); if (error) return error; error = xfs_rtginode_load_parent(tp); xfs_trans_cancel(tp); if (error == -ENOENT) error = xfs_rtginode_mkdir_parent(mp); if (error) return error; } return 0; } static bool xfs_grow_last_rtg( struct xfs_mount *mp) { if (!xfs_has_rtgroups(mp)) return true; if (mp->m_sb.sb_rgcount == 0) return false; return xfs_rtgroup_extents(mp, mp->m_sb.sb_rgcount - 1) <= mp->m_sb.sb_rgextents; } /* * Grow the realtime area of the filesystem. */ int xfs_growfs_rt( xfs_mount_t *mp, /* mount point for filesystem */ xfs_growfs_rt_t *in) /* growfs rt input struct */ struct xfs_mount *mp, struct xfs_growfs_rt *in) { xfs_rgnumber_t old_rgcount = mp->m_sb.sb_rgcount; xfs_rgnumber_t new_rgcount = 1; xfs_rgnumber_t rgno; struct xfs_buf *bp; xfs_agblock_t old_rextsize = mp->m_sb.sb_rextsize; int error; Loading Loading @@ -1134,18 +1292,56 @@ xfs_growfs_rt( if (error) goto out_unlock; error = xfs_growfs_rtg(mp, in->newblocks, in->extsize); if (xfs_has_rtgroups(mp)) { error = xfs_growfs_rt_prep_groups(mp, in->newblocks, in->extsize, &new_rgcount); if (error) goto out_unlock; } if (old_rextsize != in->extsize) { error = xfs_growfs_rt_fixup_extsize(mp); if (xfs_grow_last_rtg(mp)) { error = xfs_growfs_rtg(mp, old_rgcount - 1, in->newblocks, in->extsize); if (error) goto out_unlock; } /* Update secondary superblocks now the physical grow has completed */ error = xfs_update_secondary_sbs(mp); for (rgno = old_rgcount; rgno < new_rgcount; rgno++) { xfs_rtbxlen_t rextents = div_u64(in->newblocks, in->extsize); error = xfs_rtgroup_alloc(mp, rgno, new_rgcount, rextents); if (error) goto out_unlock; error = xfs_growfs_rtg(mp, rgno, in->newblocks, in->extsize); if (error) { struct xfs_rtgroup *rtg; rtg = xfs_rtgroup_grab(mp, rgno); if (!WARN_ON_ONCE(!rtg)) { xfs_rtunmount_rtg(rtg); xfs_rtgroup_rele(rtg); xfs_rtgroup_free(mp, rgno); } break; } } if (!error && old_rextsize != in->extsize) error = xfs_growfs_rt_fixup_extsize(mp); /* * Update secondary superblocks now the physical grow has completed. * * Also do this in case of an error as we might have already * successfully updated one or more RTGs and incremented sb_rgcount. */ if (!xfs_is_shutdown(mp)) { int error2 = xfs_update_secondary_sbs(mp); if (!error) error = error2; } out_unlock: mutex_unlock(&mp->m_growlock); Loading
fs/xfs/xfs_trans.c +9 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,10 @@ xfs_trans_mod_sb( case XFS_TRANS_SB_REXTSLOG: tp->t_rextslog_delta += delta; break; case XFS_TRANS_SB_RGCOUNT: ASSERT(delta > 0); tp->t_rgcount_delta += delta; break; default: ASSERT(0); return; Loading Loading @@ -561,6 +565,10 @@ xfs_trans_apply_sb_deltas( sbp->sb_rextslog += tp->t_rextslog_delta; whole = 1; } if (tp->t_rgcount_delta) { be32_add_cpu(&sbp->sb_rgcount, tp->t_rgcount_delta); whole = 1; } xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); if (whole) Loading Loading @@ -674,6 +682,7 @@ xfs_trans_unreserve_and_mod_sb( mp->m_sb.sb_rblocks += tp->t_rblocks_delta; mp->m_sb.sb_rextents += tp->t_rextents_delta; mp->m_sb.sb_rextslog += tp->t_rextslog_delta; mp->m_sb.sb_rgcount += tp->t_rgcount_delta; spin_unlock(&mp->m_sb_lock); /* Loading
fs/xfs/xfs_trans.h +1 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,7 @@ typedef struct xfs_trans { int64_t t_rblocks_delta;/* superblock rblocks change */ int64_t t_rextents_delta;/* superblocks rextents chg */ int64_t t_rextslog_delta;/* superblocks rextslog chg */ int64_t t_rgcount_delta; /* realtime group count */ struct list_head t_items; /* log item descriptors */ struct list_head t_busy; /* list of busy extents */ struct list_head t_dfops; /* deferred operations */ Loading