1. 26 Jan, 2023 25 commits
    • Jan Kara's avatar
      udf: Fix file corruption when appending just after end of preallocated extent · 36ec52ea
      Jan Kara authored
      When we append new block just after the end of preallocated extent, the
      code in inode_getblk() wrongly determined we're going to use the
      preallocated extent which resulted in adding block into a wrong logical
      offset in the file. Sequence like this manifests it:
      
      xfs_io -f -c "pwrite 0x2cacf 0xd122" -c "truncate 0x2dd6f" \
        -c "pwrite 0x27fd9 0x69a9" -c "pwrite 0x32981 0x7244" <file>
      
      The code that determined the use of preallocated extent is actually
      stale because udf_do_extend_file() does not create preallocation anymore
      so after calling that function we are sure there's no usable
      preallocation. Just remove the faulty condition.
      
      CC: stable@vger.kernel.org
      Fixes: 16d05565 ("udf: Discard preallocation before extending file with a hole")
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      36ec52ea
    • Jan Kara's avatar
      udf: Do not allocate blocks on page writeback · 36580ed0
      Jan Kara authored
      Now when we allocate blocks on write page fault there should be no block
      allocation happening on page writeback. So just ignore the 'create' flag
      passed to udf_get_block(). Note that we can spot dirty buffers without
      underlying blocks allocated in writeback when we race with expanding
      truncate. However in that case these buffers do not contain valid data
      so we can safely ignore them and we would just create ourselves problem
      when to trim the tail extent.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      36580ed0
    • Jan Kara's avatar
      fs: gracefully handle ->get_block not mapping bh in __mpage_writepage · 7010839c
      Jan Kara authored
      When filesystem's ->get_block function does not map the buffer head when
      called from __mpage_writepage(), the function will happily go and pass
      bogus bdev and block number to bio allocation routines which leads to
      crashes sooner or later. E.g. UDF can do this because it doesn't want to
      allocate blocks from ->writepages callbacks. It allocates blocks on
      write or page fault but writeback can still spot dirty buffers without
      underlying blocks allocated e.g. if blocksize < pagesize, the tail page
      is dirtied (which means all its buffers are dirtied), and truncate
      extends the file so that some buffer starts to be within i_size.
      Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      7010839c
    • Jan Kara's avatar
      udf: Allocate blocks on write page fault · 3c212048
      Jan Kara authored
      Currently if file with holes is mapped, udf allocates blocks for dirtied
      pages during page writeback. This however creates problems when to
      truncate final extent to proper size and currently we leave the last
      extent untruncated which violates UDF standard. So allocate blocks on
      write page fault instead. In that case the last extent gets truncated
      the file is closed and everything is happy.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      3c212048
    • Jan Kara's avatar
      udf: Protect truncate and file type conversion with invalidate_lock · b9a861fd
      Jan Kara authored
      Protect truncate and file type conversion in udf_file_write_iter() with
      invalidate lock. That will allow us to serialize these paths with page
      faults so that the page fault can determine the file type in a racefree
      way.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      b9a861fd
    • Jan Kara's avatar
      udf: Simplify error handling in udf_file_write_iter() · 96eeaaae
      Jan Kara authored
      When udf_expand_file_adinicb() fails, we can now use the standard exit
      path instead of implementing our own.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      96eeaaae
    • Jan Kara's avatar
      udf: Push i_data_sem locking into udf_extend_file() · 2d532616
      Jan Kara authored
      Push i_data_sem locking into udf_extend_file(). It somewhat simplifies
      the code around it.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      2d532616
    • Jan Kara's avatar
      udf: Push i_data_sem locking into udf_expand_file_adinicb() · 6a3b37e0
      Jan Kara authored
      The checks we do in udf_setsize() and udf_file_write_iter() are safe to
      do only with i_rwsem locked as it stabilizes both file type and file
      size. Hence we don't need to lock i_data_sem before we enter
      udf_expand_file_adinicb() which simplifies the locking somewhat.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      6a3b37e0
    • Jan Kara's avatar
      udf: Protect rename against modification of moved directory · f950fd05
      Jan Kara authored
      When we are renaming a directory to a different directory, we need to
      update '..' entry in the moved directory. However nothing prevents moved
      directory from being modified and even converted from the in-ICB format
      to the normal format which results in a crash. Fix the problem by
      locking the moved directory.
      
      Reported-by: syzbot+aebf90eea2671c43112a@syzkaller.appspotmail.com
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      f950fd05
    • Jan Kara's avatar
      udf: Fold udf_getblk() into udf_bread() · 32f123a3
      Jan Kara authored
      udf_getblk() has a single call site. Fold it there.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      32f123a3
    • Jan Kara's avatar
      udf: Use udf_map_block() in udf_getblk() · 541e047b
      Jan Kara authored
      Use the new function udf_map_block() in udf_getblk().
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      541e047b
    • Jan Kara's avatar
      udf: Add flag to disable block preallocation · 80942521
      Jan Kara authored
      In some cases we don't want to create block preallocation when
      allocating blocks. Add a flag to udf_map_rq controlling the behavior.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      80942521
    • Jan Kara's avatar
      udf: Pass mapping request into inode_getblk() · b3c03fce
      Jan Kara authored
      Pass struct udf_map_rq into inode_getblk() instead of unfolding it and
      the putting the results back.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      b3c03fce
    • Jan Kara's avatar
      udf: Fold udf_block_map() into udf_map_block() · 364a6665
      Jan Kara authored
      udf_block_map() has now only a single caller. Fold it there.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      364a6665
    • Jan Kara's avatar
      udf: Convert udf_symlink_filler() to use udf_bread() · 15a08f51
      Jan Kara authored
      Convert udf_symlink_filler() to use udf_bread() instead of mapping and
      reading buffer head manually.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      15a08f51
    • Jan Kara's avatar
      udf: Do not call udf_block_map() on ICB files · f33321b2
      Jan Kara authored
      Currently udf_symlink_filler() called udf_block_map() even on files
      which have data stored inside the ICB. This is invalid as we cannot map
      blocks for such files (although so far the error got silently ignored).
      The call happened because we could not call block mapping function once
      we've acquired i_data_sem and determined whether the file has data
      stored in the ICB. For symlinks the situation is luckily simple as they
      get never modified so file type never changes once it is set. Hence we
      can check the file type even without i_data_sem. Just drop the
      i_data_sem locking and move block mapping to where it is needed.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      f33321b2
    • Jan Kara's avatar
      udf: Use udf_bread() in udf_load_vat() · 08931b78
      Jan Kara authored
      Use udf_bread() instead of mapping and loadign buffer head manually in
      udf_load_vat().
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      08931b78
    • Jan Kara's avatar
      udf: Use udf_bread() in udf_get_pblock_virt15() · 4215db46
      Jan Kara authored
      Use udf_bread() instead of mapping and reading buffer head manually in
      udf_get_pblock_virt15().
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      4215db46
    • Jan Kara's avatar
      udf: Factor out block mapping into udf_map_block() · f3a30be7
      Jan Kara authored
      Create new block mapping function udf_map_block() that takes new
      udf_map_rq structure describing mapping request. We will convert other
      places to use this function for block mapping.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      f3a30be7
    • Jan Kara's avatar
      udf: Move incrementing of goal block directly into inode_getblk() · de80dae0
      Jan Kara authored
      inode_getblk() sets goal block for the next allocation to the currently
      allocated block. This is obviously one less than what the goal block
      should be which we fixup in udf_get_block(). Just set the right goal
      block directly in inode_getblk().
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      de80dae0
    • Jan Kara's avatar
      udf: Drop VARCONV support · 101ee137
      Jan Kara authored
      UDF was supporting a strange mode where the media was containing 7
      blocks of unknown data for every 32 blocks of the filesystem. I have yet
      to see the media that would need such conversion (maybe it comes from
      packet writing times) and the conversions have been inconsistent in the
      code. In particular any write will write to a wrong block and corrupt
      the media. This is an indication and no user actually needs this so
      let's just drop the support instead of trying to fix it.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      101ee137
    • Jan Kara's avatar
      udf: Unify types in anchor block detection · bd904f3c
      Jan Kara authored
      When detecting last recorded block and from it derived anchor block
      position, we were mixing unsigned long, u32, and sector_t types. Since
      udf supports only 32-bit block numbers this is harmless but sometimes
      makes things awkward. Convert everything to udf_pblk_t and also handle
      the situation when block device size would not fit into udf_pblk_t.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      bd904f3c
    • Jan Kara's avatar
      udf: Fix directory iteration for longer tail extents · 1ea1cd11
      Jan Kara authored
      When directory's last extent has more that one block and its length is
      not multiple of a block side, the code wrongly decided to move to the
      next extent instead of processing the last partial block. This led to
      directory corruption. Fix the rounding issue.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      1ea1cd11
    • Jan Kara's avatar
      udf: Propagate errors from udf_advance_blk() · ee454ad2
      Jan Kara authored
      When we spot directory corruption when trying to load next directory
      extent, we didn't propagate the error up properly, leading to possibly
      indefinite looping on corrupted directories. Fix the problem by
      propagating the error properly.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      ee454ad2
    • Jan Kara's avatar
      udf: Zero udf name padding · 3bea4ae1
      Jan Kara authored
      Padding of name in the directory entry needs to be zeroed out. Fix it.
      Signed-off-by: default avatarJan Kara <jack@suse.cz>
      3bea4ae1
  2. 16 Jan, 2023 1 commit
  3. 09 Jan, 2023 14 commits