anchor.diff:                     (iter (for block-n :from (extent-start-block extent))
                            (repeat (extent-length extent))
                            (funcall fn (read-block disk superblock block-n))))))
  -          ((= +inline-data-flag+ (logand +inline-data-flag+ inode-flags))
  +          ((logbitp +inline-data-flag+ inode-flags)
              (funcall fn inode-block))
             (t
              (iter (for offset :from 0 :below 48 :by 4)
  
positive.code: (in-package :mezzano.ext4-file-system)
  
  ;; Compatible feature set flags.
  (defconstant +compat-dir-prealloc+ #x1)
  (defconstant +compat-imagic-inodes+ #x2)
  (defconstant +compat-has-journal+ #x4)
  (defconstant +compat-ext-attr+ #x8)
  (defconstant +compat-resize-inode+ #x10)
  (defconstant +compat-dir-index+ #x20)
  (defconstant +compat-lazy-bg+ #x40)
  (defconstant +compat-exclude-inode+ #x80)
  (defconstant +compat-exclude-bitmap+ #x100)
  (defconstant +compat-sparse-super2+ #x200)
  
  ;; Incompatible feature set.
  (defconstant +incompat-compression+ #x1)
  (defconstant +incompat-filetype+ #x2)
  (defconstant +incompat-recover+ #x4)
  (defconstant +incompat-journal-dev+ #x8)
  (defconstant +incompat-meta-bg+ #x10)
  (defconstant +incompat-extents+ #x40)
  (defconstant +incompat-64bit+ #x80)
  (defconstant +incompat-mmp+ #x100)
  (defconstant +incompat-flex-bg+ #x200)
  (defconstant +incompat-ea-inode+ #x400)
  (defconstant +incompat-dirdata+ #x1000)
  (defconstant +incompat-csum-seed+ #x2000)
  (defconstant +incompat-largedir+ #x4000)
  (defconstant +incompat-inline-data+ #x8000)
  (defconstant +incompat-encrypt+ #x10000)
  
  ;; Readonly-compatible feature set.
  (defconstant +ro-compat-sparse-super+ #x1)
  (defconstant +ro-compat-large-file+ #x2)
  (defconstant +ro-compat-btree-dir+ #x4)
  (defconstant +ro-compat-huge-file+ #x8)
  (defconstant +ro-compat-gdt-csum+ #x10)
  (defconstant +ro-compat-dir-nlink+ #x20)
  (defconstant +ro-compat-extra-isize+ #x40)
  (defconstant +ro-compat-has-snapshot+ #x80)
  (defconstant +ro-compat-quota+ #x100)
  (defconstant +ro-compat-bigalloc+ #x200)
  (defconstant +ro-compat-metadata-csum+ #x400)
  (defconstant +ro-compat-replica+ #x800)
  (defconstant +ro-compat-readonly+ #x1000)
  (defconstant +ro-compat-project+ #x2000)
  
  ;; Inode flags
  (defconstant +sync-flag+ #x8 "All writes to the file must be synchronous")
  (defconstant +immutable-flag+ #x10 "File is immutable")
  (defconstant +append-flag+ #x20 "File can only be appended")
  (defconstant +noatime-flag+ #x80 "Do not update access time")
  (defconstant +encrypt-flag+ #x800 "Encrypted inode")
  (defconstant +hashed-indexes-flag+ #x1000 "Directory has hashed indexes")
  (defconstant +imagic-flag+ #x2000 "AFS magic directory")
  (defconstant +journal-data-flag+ #x4000 "File data must always be written through the journal")
  (defconstant +notail-flag+ #x8000 "File tail should not be merged (not used by ext4)")
  (defconstant +dirsync-flag+ #x10000 "All directory entry data should be written synchronously")
  (defconstant +topdir-flag+ #x20000 "Top of directory hierarchy")
  (defconstant +huge-file-flag+ #x40000 "This is a huge file")
  (defconstant +extents-flag+ #x80000 "Inode uses extents")
  (defconstant +ea-inode-flag+ #x200000 "Inode stores a large extended attribute value in its data blocks")
  (defconstant +inline-data-flag+ #x10000000 "Inode has inline data")
  
  ;; Directory file types
  (defconstant +unknown-type+ #x0)
  
negative.code: (defun read-extent (inode-block offset)
    (let ((length (sys.int::ub16ref/le inode-block (+ 4 offset))))
      (when (> length 32768)
        ;; TODO: support uninitialized extent
        (error "Uninitialized extent not suported"))
      (make-extent :n-block (sys.int::ub16ref/le inode-block offset)
                   :length length
  