@@ -989,6 +989,41 @@ u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start,
989989 return pos ;
990990}
991991
992+ static bool btrfs_dev_set_active_zone (struct btrfs_device * device , u64 pos )
993+ {
994+ struct btrfs_zoned_device_info * zone_info = device -> zone_info ;
995+ unsigned int zno = (pos >> zone_info -> zone_size_shift );
996+
997+ /* We can use any number of zones */
998+ if (zone_info -> max_active_zones == 0 )
999+ return true;
1000+
1001+ if (!test_bit (zno , zone_info -> active_zones )) {
1002+ /* Active zone left? */
1003+ if (atomic_dec_if_positive (& zone_info -> active_zones_left ) < 0 )
1004+ return false;
1005+ if (test_and_set_bit (zno , zone_info -> active_zones )) {
1006+ /* Someone already set the bit */
1007+ atomic_inc (& zone_info -> active_zones_left );
1008+ }
1009+ }
1010+
1011+ return true;
1012+ }
1013+
1014+ static void btrfs_dev_clear_active_zone (struct btrfs_device * device , u64 pos )
1015+ {
1016+ struct btrfs_zoned_device_info * zone_info = device -> zone_info ;
1017+ unsigned int zno = (pos >> zone_info -> zone_size_shift );
1018+
1019+ /* We can use any number of zones */
1020+ if (zone_info -> max_active_zones == 0 )
1021+ return ;
1022+
1023+ if (test_and_clear_bit (zno , zone_info -> active_zones ))
1024+ atomic_inc (& zone_info -> active_zones_left );
1025+ }
1026+
9921027int btrfs_reset_device_zone (struct btrfs_device * device , u64 physical ,
9931028 u64 length , u64 * bytes )
9941029{
@@ -1004,6 +1039,7 @@ int btrfs_reset_device_zone(struct btrfs_device *device, u64 physical,
10041039 * bytes = length ;
10051040 while (length ) {
10061041 btrfs_dev_set_zone_empty (device , physical );
1042+ btrfs_dev_clear_active_zone (device , physical );
10071043 physical += device -> zone_info -> zone_size ;
10081044 length -= device -> zone_info -> zone_size ;
10091045 }
@@ -1656,3 +1692,160 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info,
16561692
16571693 return device ;
16581694}
1695+
1696+ /**
1697+ * Activate block group and underlying device zones
1698+ *
1699+ * @block_group: the block group to activate
1700+ *
1701+ * Return: true on success, false otherwise
1702+ */
1703+ bool btrfs_zone_activate (struct btrfs_block_group * block_group )
1704+ {
1705+ struct btrfs_fs_info * fs_info = block_group -> fs_info ;
1706+ struct map_lookup * map ;
1707+ struct btrfs_device * device ;
1708+ u64 physical ;
1709+ bool ret ;
1710+
1711+ if (!btrfs_is_zoned (block_group -> fs_info ))
1712+ return true;
1713+
1714+ map = block_group -> physical_map ;
1715+ /* Currently support SINGLE profile only */
1716+ ASSERT (map -> num_stripes == 1 );
1717+ device = map -> stripes [0 ].dev ;
1718+ physical = map -> stripes [0 ].physical ;
1719+
1720+ if (device -> zone_info -> max_active_zones == 0 )
1721+ return true;
1722+
1723+ spin_lock (& block_group -> lock );
1724+
1725+ if (block_group -> zone_is_active ) {
1726+ ret = true;
1727+ goto out_unlock ;
1728+ }
1729+
1730+ /* No space left */
1731+ if (block_group -> alloc_offset == block_group -> zone_capacity ) {
1732+ ret = false;
1733+ goto out_unlock ;
1734+ }
1735+
1736+ if (!btrfs_dev_set_active_zone (device , physical )) {
1737+ /* Cannot activate the zone */
1738+ ret = false;
1739+ goto out_unlock ;
1740+ }
1741+
1742+ /* Successfully activated all the zones */
1743+ block_group -> zone_is_active = 1 ;
1744+
1745+ spin_unlock (& block_group -> lock );
1746+
1747+ /* For the active block group list */
1748+ btrfs_get_block_group (block_group );
1749+
1750+ spin_lock (& fs_info -> zone_active_bgs_lock );
1751+ ASSERT (list_empty (& block_group -> active_bg_list ));
1752+ list_add_tail (& block_group -> active_bg_list , & fs_info -> zone_active_bgs );
1753+ spin_unlock (& fs_info -> zone_active_bgs_lock );
1754+
1755+ return true;
1756+
1757+ out_unlock :
1758+ spin_unlock (& block_group -> lock );
1759+ return ret ;
1760+ }
1761+
1762+ int btrfs_zone_finish (struct btrfs_block_group * block_group )
1763+ {
1764+ struct btrfs_fs_info * fs_info = block_group -> fs_info ;
1765+ struct map_lookup * map ;
1766+ struct btrfs_device * device ;
1767+ u64 physical ;
1768+ int ret = 0 ;
1769+
1770+ if (!btrfs_is_zoned (fs_info ))
1771+ return 0 ;
1772+
1773+ map = block_group -> physical_map ;
1774+ /* Currently support SINGLE profile only */
1775+ ASSERT (map -> num_stripes == 1 );
1776+
1777+ device = map -> stripes [0 ].dev ;
1778+ physical = map -> stripes [0 ].physical ;
1779+
1780+ if (device -> zone_info -> max_active_zones == 0 )
1781+ return 0 ;
1782+
1783+ spin_lock (& block_group -> lock );
1784+ if (!block_group -> zone_is_active ) {
1785+ spin_unlock (& block_group -> lock );
1786+ return 0 ;
1787+ }
1788+
1789+ /* Check if we have unwritten allocated space */
1790+ if ((block_group -> flags &
1791+ (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM )) &&
1792+ block_group -> alloc_offset > block_group -> meta_write_pointer ) {
1793+ spin_unlock (& block_group -> lock );
1794+ return - EAGAIN ;
1795+ }
1796+ spin_unlock (& block_group -> lock );
1797+
1798+ ret = btrfs_inc_block_group_ro (block_group , false);
1799+ if (ret )
1800+ return ret ;
1801+
1802+ /* Ensure all writes in this block group finish */
1803+ btrfs_wait_block_group_reservations (block_group );
1804+ /* No need to wait for NOCOW writers. Zoned mode does not allow that. */
1805+ btrfs_wait_ordered_roots (fs_info , U64_MAX , block_group -> start ,
1806+ block_group -> length );
1807+
1808+ spin_lock (& block_group -> lock );
1809+
1810+ /*
1811+ * Bail out if someone already deactivated the block group, or
1812+ * allocated space is left in the block group.
1813+ */
1814+ if (!block_group -> zone_is_active ) {
1815+ spin_unlock (& block_group -> lock );
1816+ btrfs_dec_block_group_ro (block_group );
1817+ return 0 ;
1818+ }
1819+
1820+ if (block_group -> reserved ) {
1821+ spin_unlock (& block_group -> lock );
1822+ btrfs_dec_block_group_ro (block_group );
1823+ return - EAGAIN ;
1824+ }
1825+
1826+ block_group -> zone_is_active = 0 ;
1827+ block_group -> alloc_offset = block_group -> zone_capacity ;
1828+ block_group -> free_space_ctl -> free_space = 0 ;
1829+ btrfs_clear_treelog_bg (block_group );
1830+ spin_unlock (& block_group -> lock );
1831+
1832+ ret = blkdev_zone_mgmt (device -> bdev , REQ_OP_ZONE_FINISH ,
1833+ physical >> SECTOR_SHIFT ,
1834+ device -> zone_info -> zone_size >> SECTOR_SHIFT ,
1835+ GFP_NOFS );
1836+ btrfs_dec_block_group_ro (block_group );
1837+
1838+ if (!ret ) {
1839+ btrfs_dev_clear_active_zone (device , physical );
1840+
1841+ spin_lock (& fs_info -> zone_active_bgs_lock );
1842+ ASSERT (!list_empty (& block_group -> active_bg_list ));
1843+ list_del_init (& block_group -> active_bg_list );
1844+ spin_unlock (& fs_info -> zone_active_bgs_lock );
1845+
1846+ /* For active_bg_list */
1847+ btrfs_put_block_group (block_group );
1848+ }
1849+
1850+ return ret ;
1851+ }
0 commit comments