btrfs / btrfs-todo

An issues only repo to organize our TODO items
21 stars 2 forks source link

Drastically reduce lock_extent/unlock_extent usage #55

Open josefbacik opened 6 months ago

josefbacik commented 6 months ago

lock_extent/unlock_extent are widely used, but we are for the most part protected by higher up locks. This adds a lot of complexity to the code, and we do not have good introspection into them because they don't give us any lockdep annotations. When attempting to convert their usage to a rwsem I immediately uncovered a deadlock in fiemap thanks to lockdep. We currently use this as a catch all "lock this range and check ordered extent and mess with the file extents", but we don't necessarily need this protection.

  1. Buffered writes. For buffered writes we are holding the inode lock and the page locks for the range. This protects us from simultaneous direct writes, direct reads, mmap, fallocate, and fiemap.
  2. Buffered reads. Again, we're holding the page lock, so we know the extent we look up will be stable while we're doing the read.
  3. Mmap. The page lock saves us here again for buffered operations, and the i_mmap_lock saves us from remapping and reflink. We would probably still need to maintain extent locking here because of direct io.
  4. Direct writes. Here we need to maintain the extent locking, we would simply only use extent locking for direct writes, to allow for parallel, non-overlapping writes to the same file.

We could rip out the extent locking from the buffered case, excepting page_mkwrite. This would reduce the usage down to three easy to contain areas, and would make the buffered case much faster and cleaner.