• Boris Burkov's avatar
    btrfs: qgroup: flush reservations during quota disable · af0e2aab
    Boris Burkov authored
    The following sequence:
    
      enable simple quotas
      do some writes
          reserve space
          create ordered_extent
    	  release rsv (store rsv_bytes in OE, mark QGROUP_RESERVED bits)
      disable quotas
      enable simple quotas
          set qgroup rsv to 0 on all subvolumes
      ordered_extent finishes
          create delayed ref with rsv_bytes from before
      run delayed ref
          record_simple_quota_delta
    	  free rsv_bytes (0 -> -rsv_delta)
    
    results in us reliably underflowing the subvolume's qgroup rsv counter,
    because disabling/re-enabling quotas toggles reservation counters down
    to 0, but does not remove other file system state which represents
    successful acquisition of qgroup rsv space. Specifically metadata rsv
    counters on the root object and rsv_bytes on ordered_extent objects that
    have released their reservation as well as the corresponding
    QGROUP_RESERVED extent bits.
    
    Normal qgroups gets away with this, I believe because it forces more
    work to happen on transaction commit, but I am not certain it is totally
    safe from the ordered_extent/leaked extent bit variant. Simple quotas
    hits this reliably.
    
    The intent of the fix is to make disable take the time to clear that
    external to qgroups state as well: after flipping off the quota bit on
    fs_info, flush delalloc and ordered extents, clearing the extent bits
    along the way. This makes it so there are no ordered extents or meta
    prealloc hanging around from the first enablement period during the second.
    Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Signed-off-by: default avatarBoris Burkov <boris@bur.io>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    af0e2aab
qgroup.c 121 KB