1. 14 2月, 2017 32 次提交
  2. 11 2月, 2017 1 次提交
    • O
      Btrfs: fix btrfs_decompress_buf2page() · 6e78b3f7
      Omar Sandoval 提交于
      If btrfs_decompress_buf2page() is handed a bio with its page in the
      middle of the working buffer, then we adjust the offset into the working
      buffer. After we copy into the bio, we advance the iterator by the
      number of bytes we copied. Then, we have some logic to handle the case
      of discontiguous pages and adjust the offset into the working buffer
      again. However, if we didn't advance the bio to a new page, we may enter
      this case in error, essentially repeating the adjustment that we already
      made when we entered the function. The end result is bogus data in the
      bio.
      
      Previously, we only checked for this case when we advanced to a new
      page, but the conversion to bio iterators changed that. This restores
      the old, correct behavior.
      
      A case I saw when testing with zlib was:
      
          buf_start = 42769
          total_out = 46865
          working_bytes = total_out - buf_start = 4096
          start_byte = 45056
      
      The condition (total_out > start_byte && buf_start < start_byte) is
      true, so we adjust the offset:
      
          buf_offset = start_byte - buf_start = 2287
          working_bytes -= buf_offset = 1809
          current_buf_start = buf_start = 42769
      
      Then, we copy
      
          bytes = min(bvec.bv_len, PAGE_SIZE - buf_offset, working_bytes) = 1809
          buf_offset += bytes = 4096
          working_bytes -= bytes = 0
          current_buf_start += bytes = 44578
      
      After bio_advance(), we are still in the same page, so start_byte is the
      same. Then, we check (total_out > start_byte && current_buf_start < start_byte),
      which is true! So, we adjust the values again:
      
          buf_offset = start_byte - buf_start = 2287
          working_bytes = total_out - start_byte = 1809
          current_buf_start = buf_start + buf_offset = 45056
      
      But note that working_bytes was already zero before this, so we should
      have stopped copying.
      
      Fixes: 974b1adc ("btrfs: use bio iterators for the decompression handlers")
      Reported-by: NPat Erley <pat-lkml@erley.org>
      Reviewed-by: NChris Mason <clm@fb.com>
      Signed-off-by: NOmar Sandoval <osandov@fb.com>
      Signed-off-by: NChris Mason <clm@fb.com>
      Reviewed-by: NLiu Bo <bo.li.liu@oracle.com>
      Tested-by: NLiu Bo <bo.li.liu@oracle.com>
      6e78b3f7
  3. 09 2月, 2017 1 次提交
  4. 27 1月, 2017 3 次提交
  5. 20 1月, 2017 3 次提交
    • L
      Btrfs: fix truncate down when no_holes feature is enabled · 91298eec
      Liu Bo 提交于
      For such a file mapping,
      
      [0-4k][hole][8k-12k]
      
      In NO_HOLES mode, we don't have the [hole] extent any more.
      Commit c1aa4575 ("Btrfs: fix shrinking truncate when the no_holes feature is enabled")
       fixed disk isize not being updated in NO_HOLES mode when data is not flushed.
      
      However, even if data has been flushed, we can still have trouble
      in updating disk isize since we updated disk isize to 'start' of
      the last evicted extent.
      Reviewed-by: NChris Mason <clm@fb.com>
      Signed-off-by: NLiu Bo <bo.li.liu@oracle.com>
      Signed-off-by: NDavid Sterba <dsterba@suse.com>
      91298eec
    • C
      Btrfs: Fix deadlock between direct IO and fast fsync · 97dcdea0
      Chandan Rajendra 提交于
      The following deadlock is seen when executing generic/113 test,
      
       ---------------------------------------------------------+----------------------------------------------------
        Direct I/O task                                           Fast fsync task
       ---------------------------------------------------------+----------------------------------------------------
        btrfs_direct_IO
          __blockdev_direct_IO
           do_blockdev_direct_IO
            do_direct_IO
             btrfs_get_blocks_direct
              while (blocks needs to written)
               get_more_blocks (first iteration)
                btrfs_get_blocks_direct
                 btrfs_create_dio_extent
                   down_read(&BTRFS_I(inode) >dio_sem)
                   Create and add extent map and ordered extent
                   up_read(&BTRFS_I(inode) >dio_sem)
                                                                  btrfs_sync_file
                                                                    btrfs_log_dentry_safe
                                                                     btrfs_log_inode_parent
                                                                      btrfs_log_inode
                                                                       btrfs_log_changed_extents
                                                                        down_write(&BTRFS_I(inode) >dio_sem)
                                                                         Collect new extent maps and ordered extents
                                                                          wait for ordered extent completion
               get_more_blocks (second iteration)
                btrfs_get_blocks_direct
                 btrfs_create_dio_extent
                   down_read(&BTRFS_I(inode) >dio_sem)
       --------------------------------------------------------------------------------------------------------------
      
      In the above description, Btrfs direct I/O code path has not yet started
      submitting bios for file range covered by the initial ordered
      extent. Meanwhile, The fast fsync task obtains the write semaphore and
      waits for I/O on the ordered extent to get completed. However, the
      Direct I/O task is now blocked on obtaining the read semaphore.
      
      To resolve the deadlock, this commit modifies the Direct I/O code path
      to obtain the read semaphore before invoking
      __blockdev_direct_IO(). The semaphore is then given up after
      __blockdev_direct_IO() returns. This allows the Direct I/O code to
      complete I/O on all the ordered extents it creates.
      Signed-off-by: NChandan Rajendra <chandan@linux.vnet.ibm.com>
      Reviewed-by: NFilipe Manana <fdmanana@suse.com>
      Signed-off-by: NDavid Sterba <dsterba@suse.com>
      97dcdea0
    • W
      btrfs: fix false enospc error when truncating heavily reflinked file · 47b5d646
      Wang Xiaoguang 提交于
      Below test script can reveal this bug:
          dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100
          dev=$(losetup --show -f fs.img)
          mkdir -p /mnt/mntpoint
          mkfs.btrfs  -f $dev
          mount $dev /mnt/mntpoint
          cd /mnt/mntpoint
      
          echo "workdir is: /mnt/mntpoint"
          blocksize=$((128 * 1024))
          dd if=/dev/zero of=testfile bs=$blocksize count=1
          sync
          count=$((17*1024*1024*1024/blocksize))
          echo "file size is:" $((count*blocksize))
          for ((i = 1; i <= $count; i++)); do
              dst_offset=$((blocksize * i))
              xfs_io -f -c "reflink testfile 0 $dst_offset $blocksize"\
                      testfile > /dev/null
          done
          sync
          truncate --size 0 testfile
      
      The last truncate operation will fail for ENOSPC reason, but indeed
      it should not fail.
      
      In btrfs_truncate(), we use a temporary block_rsv to do truncate
      operation. With every btrfs_truncate_inode_items() call, we migrate space
      to this block_rsv, but forget to cleanup previous reservation, which
      will make this block_rsv's reserved bytes keep growing, and this reserved
      space will only be released in the end of btrfs_truncate(), this metadata
      leak will impact other's metadata reservation. In this case, it's
      "btrfs_start_transaction(root, 2);" fails for enospc error, which make
      this truncate operation fail.
      
      Call btrfs_block_rsv_release() to fix this bug.
      Signed-off-by: NWang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
      Reviewed-by: NDavid Sterba <dsterba@suse.com>
      Signed-off-by: NDavid Sterba <dsterba@suse.com>
      47b5d646