This project is mirrored from Pull mirroring updated .
  1. 18 Aug, 2009 1 commit
    • Jan Kara's avatar
      ext4: Fix possible deadlock between ext4_truncate() and ext4_get_blocks() · 487caeef
      Jan Kara authored
      During truncate we are sometimes forced to start a new transaction as
      the amount of blocks to be journaled is both quite large and hard to
      predict. So far we restarted a transaction while holding i_data_sem
      and that violates lock ordering because i_data_sem ranks below a
      transaction start (and it can lead to a real deadlock with
      ext4_get_blocks() mapping blocks in some page while having a
      transaction open).
      We fix the problem by dropping the i_data_sem before restarting the
      transaction and acquire it afterwards. It's slightly subtle that this
      1) By the time ext4_truncate() is called, all the page cache for the
      truncated part of the file is dropped so get_block() should not be
      called on it (we only have to invalidate extent cache after we
      reacquire i_data_sem because some extent from not-truncated part could
      extend also into the part we are going to truncate).
      2) Writes, migrate or defrag hold i_mutex so they are stopped for all
      the time of the truncate.
      This bug has been found and analyzed by Theodore Tso <>.
      Signed-off-by: default avatarJan Kara <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  2. 11 Aug, 2009 1 commit
  3. 17 Jul, 2009 1 commit
    • Curt Wohlgemuth's avatar
      ext4: More buffer head reference leaks · 6487a9d3
      Curt Wohlgemuth authored
      After the patch I posted last week regarding buffer head ref leaks in
      no-journal mode, I looked at all the code that uses buffer heads and
      searched for more potential leaks.
      The patch below fixes the issues I found; these can occur even when a
      journal is present.
      The change to inode.c fixes a double release if
      ext4_journal_get_create_access() fails.
      The changes to namei.c are more complicated.  add_dirent_to_buf() will
      release the input buffer head EXCEPT when it returns -ENOSPC.  There are
      some callers of this routine that don't always do the brelse() in the event
      that -ENOSPC is returned.  Unfortunately, to put this fix into ext4_add_entry()
      required capturing the return value of make_indexed_dir() and
      Signed-off-by: default avatarCurt Wohlgemuth <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  4. 13 Jul, 2009 1 commit
    • Curt Wohlgemuth's avatar
      ext4: Fix buffer head reference leak in no-journal mode · e6b5d301
      Curt Wohlgemuth authored
      We found a problem with buffer head reference leaks when using an ext4
      partition without a journal.  In particular, calls to ext4_forget() would
      not to a brelse() on the input buffer head, which will cause pages they
      belong to to not be reclaimable.
      Further investigation showed that all places where ext4_journal_forget() and
      ext4_journal_revoke() are called are subject to the same problem.  The patch
      below changes __ext4_journal_forget/__ext4_journal_revoke to do an explicit
      release of the buffer head when the journal handle isn't valid.
      Signed-off-by: default avatarCurt Wohlgemuth <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  5. 24 Jun, 2009 1 commit
  6. 15 Jun, 2009 1 commit
    • Theodore Ts'o's avatar
      ext4: Don't update ctime for non-extent-mapped inodes · 41591750
      Theodore Ts'o authored
      The VFS handles updating ctime, so we don't need to update the inode's
      ctime in ext4_splace_branch() to update the direct or indirect blocks.
      This was harmless when we did this in ext3, but in ext4, thanks to
      delayed allocation, updating the ctime in ext4_splice_branch() can
      cause the ctime to mysteriously jump when the blocks are finally
      Thanks to Björn Steinbrink for pointing out this problem on the git
      mailing list.
      Signed-off-by: default avatar"Theodore Ts'o" <>
  7. 14 Jun, 2009 4 commits
  8. 13 Jun, 2009 2 commits
  9. 09 Jun, 2009 1 commit
  10. 05 Jun, 2009 2 commits
  11. 09 Jun, 2009 1 commit
    • Jan Kara's avatar
      ext4: Get rid of EXTEND_DISKSIZE flag of ext4_get_blocks_handle() · 03f5d8bc
      Jan Kara authored
      Get rid of EXTEND_DISKSIZE flag of ext4_get_blocks_handle(). This
      seems to be a relict from some old days and setting disksize in this
      function does not make much sense.  Currently it was set only by
      ext4_getblk().  Since the parameter has some effect only if create ==
      1, it is easy to check by grepping through the sources that the three
      callers which end up calling ext4_getblk() with create == 1
      (ext4_append, ext4_quota_write, ext4_mkdir) do the right thing and set
      disksize themselves.
      Signed-off-by: default avatarJan Kara <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  12. 04 Jun, 2009 1 commit
  13. 13 Jul, 2009 1 commit
    • Jan Kara's avatar
      ext4: Fix truncation of symlinks after failed write · ffacfa7a
      Jan Kara authored
      Contents of long symlinks is written via standard write methods. So
      when the write fails, we add inode to orphan list. But symlinks don't
      have .truncate method defined so nobody properly removes them from the
      on disk orphan list.
      Fix this by calling ext4_truncate() directly instead of calling
      vmtruncate() (which is saner anyway since we don't need anything
      vmtruncate() does except from calling .truncate in these paths).  We
      also add inode to orphan list only if ext4_can_truncate() is true
      (currently, it can be false for symlinks when there are no blocks
      allocated) - otherwise orphan list processing will complain and
      ext4_truncate() will not remove inode from on-disk orphan list.
      Signed-off-by: default avatarJan Kara <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  14. 06 Jul, 2009 1 commit
    • Theodore Ts'o's avatar
      ext4: Fix potential reclaim deadlock when truncating partial block · f4a01017
      Theodore Ts'o authored
      The ext4_block_truncate_page() function previously called
      grab_cache_page(), which called find_or_create_page() with the
      __GFP_FS flag potentially set.  This could cause a deadlock if the
      system is low on memory and it attempts a memory reclaim, which could
      potentially call back into ext4.  So we need to call
      find_or_create_page() directly, and remove the __GFP_FP flag to avoid
      this potential deadlock.
      Thanks to Roland Dreier for reporting a lockdep warning which showed
      this problem.
      [20786.363249] =================================
      [20786.363257] [ INFO: inconsistent lock state ]
      [20786.363265] 2.6.31-2-generic #14~rbd4gitd960eea9
      [20786.363270] ---------------------------------
      [20786.363276] inconsistent {IN-RECLAIM_FS-W} -> {RECLAIM_FS-ON-W} usage.
      [20786.363285] http/8397 [HC0[0]:SC0[0]:HE1:SE1] takes:
      [20786.363291]  (jbd2_handle){+.+.?.}, at: [<ffffffff812008bb>] jbd2_journal_start+0xdb/0x150
      [20786.363314] {IN-RECLAIM_FS-W} state was registered at:
      [20786.363320]   [<ffffffff8108bef6>] mark_irqflags+0xc6/0x1a0
      [20786.363334]   [<ffffffff8108d347>] __lock_acquire+0x287/0x430
      [20786.363345]   [<ffffffff8108d595>] lock_acquire+0xa5/0x150
      [20786.363355]   [<ffffffff812008da>] jbd2_journal_start+0xfa/0x150
      [20786.363365]   [<ffffffff811d98a8>] ext4_journal_start_sb+0x58/0x90
      [20786.363377]   [<ffffffff811cce85>] ext4_delete_inode+0xc5/0x2c0
      [20786.363389]   [<ffffffff81146fa3>] generic_delete_inode+0xd3/0x1a0
      [20786.363401]   [<ffffffff81147095>] generic_drop_inode+0x25/0x30
      [20786.363411]   [<ffffffff81145ce2>] iput+0x62/0x70
      [20786.363420]   [<ffffffff81142878>] dentry_iput+0x98/0x110
      [20786.363429]   [<ffffffff81142a00>] d_kill+0x50/0x80
      [20786.363438]   [<ffffffff811444c5>] dput+0x95/0x180
      [20786.363447]   [<ffffffff8120de4b>] ecryptfs_d_release+0x2b/0x70
      [20786.363459]   [<ffffffff81142978>] d_free+0x28/0x60
      [20786.363468]   [<ffffffff81142a18>] d_kill+0x68/0x80
      [20786.363477]   [<ffffffff81142ad3>] prune_one_dentry+0xa3/0xc0
      [20786.363487]   [<ffffffff81142d61>] __shrink_dcache_sb+0x271/0x290
      [20786.363497]   [<ffffffff81142e89>] prune_dcache+0x109/0x1b0
      [20786.363506]   [<ffffffff81142f6f>] shrink_dcache_memory+0x3f/0x50
      [20786.363516]   [<ffffffff810f6d3d>] shrink_slab+0x12d/0x190
      [20786.363527]   [<ffffffff810f97d7>] balance_pgdat+0x4d7/0x640
      [20786.363537]   [<ffffffff810f9a57>] kswapd+0x117/0x170
      [20786.363546]   [<ffffffff810773ce>] kthread+0x9e/0xb0
      [20786.363558]   [<ffffffff8101430a>] child_rip+0xa/0x20
      [20786.363569]   [<ffffffffffffffff>] 0xffffffffffffffff
      [20786.363598] irq event stamp: 15997
      [20786.363603] hardirqs last  enabled at (15997): [<ffffffff81125f9d>] kmem_cache_alloc+0xfd/0x1a0
      [20786.363617] hardirqs last disabled at (15996): [<ffffffff81125f01>] kmem_cache_alloc+0x61/0x1a0
      [20786.363628] softirqs last  enabled at (15966): [<ffffffff810631ea>] __do_softirq+0x14a/0x220
      [20786.363641] softirqs last disabled at (15861): [<ffffffff8101440c>] call_softirq+0x1c/0x30
      [20786.363653] other info that might help us debug this:
      [20786.363660] 3 locks held by http/8397:
      [20786.363665]  #0:  (&sb->s_type->i_mutex_key#8){+.+.+.}, at: [<ffffffff8112ed24>] do_truncate+0x64/0x90
      [20786.363685]  #1:  (&sb->s_type->i_alloc_sem_key#5){+++++.}, at: [<ffffffff81147f90>] notify_change+0x250/0x350
      [20786.363707]  #2:  (jbd2_handle){+.+.?.}, at: [<ffffffff812008bb>] jbd2_journal_start+0xdb/0x150
      [20786.363726] stack backtrace:
      [20786.363734] Pid: 8397, comm: http Tainted: G         C 2.6.31-2-generic #14~rbd4gitd960eea9
      [20786.363741] Call Trace:
      [20786.363752]  [<ffffffff8108ad7c>] print_usage_bug+0x18c/0x1a0
      [20786.363763]  [<ffffffff8108b0c0>] ? check_usage_backwards+0x0/0xb0
      [20786.363773]  [<ffffffff8108bad2>] mark_lock_irq+0xf2/0x280
      [20786.363783]  [<ffffffff8108bd97>] mark_lock+0x137/0x1d0
      [20786.363793]  [<ffffffff8108c03c>] mark_held_locks+0x6c/0xa0
      [20786.363803]  [<ffffffff8108c11f>] lockdep_trace_alloc+0xaf/0xe0
      [20786.363813]  [<ffffffff810efbac>] __alloc_pages_nodemask+0x7c/0x180
      [20786.363824]  [<ffffffff810e9411>] ? find_get_page+0x91/0xf0
      [20786.363835]  [<ffffffff8111d3b7>] alloc_pages_current+0x87/0xd0
      [20786.363845]  [<ffffffff810e9827>] __page_cache_alloc+0x67/0x70
      [20786.363856]  [<ffffffff810eb7df>] find_or_create_page+0x4f/0xb0
      [20786.363867]  [<ffffffff811cb3be>] ext4_block_truncate_page+0x3e/0x460
      [20786.363876]  [<ffffffff812008da>] ? jbd2_journal_start+0xfa/0x150
      [20786.363885]  [<ffffffff812008bb>] ? jbd2_journal_start+0xdb/0x150
      [20786.363895]  [<ffffffff811c6415>] ? ext4_meta_trans_blocks+0x75/0xf0
      [20786.363905]  [<ffffffff811e8d8b>] ext4_ext_truncate+0x1bb/0x1e0
      [20786.363916]  [<ffffffff811072c5>] ? unmap_mapping_range+0x75/0x290
      [20786.363926]  [<ffffffff811ccc28>] ext4_truncate+0x498/0x630
      [20786.363938]  [<ffffffff8129b4ce>] ? _raw_spin_unlock+0x5e/0xb0
      [20786.363947]  [<ffffffff81107306>] ? unmap_mapping_range+0xb6/0x290
      [20786.363957]  [<ffffffff8108c3ad>] ? trace_hardirqs_on+0xd/0x10
      [20786.363966]  [<ffffffff811ffe58>] ? jbd2_journal_stop+0x1f8/0x2e0
      [20786.363976]  [<ffffffff81107690>] vmtruncate+0xb0/0x110
      [20786.363986]  [<ffffffff81147c05>] inode_setattr+0x35/0x170
      [20786.363995]  [<ffffffff811c9906>] ext4_setattr+0x186/0x370
      [20786.364005]  [<ffffffff81147eab>] notify_change+0x16b/0x350
      [20786.364014]  [<ffffffff8112ed30>] do_truncate+0x70/0x90
      [20786.364021]  [<ffffffff8112f48b>] T.657+0xeb/0x110
      [20786.364021]  [<ffffffff8112f4be>] sys_ftruncate+0xe/0x10
      [20786.364021]  [<ffffffff81013132>] system_call_fastpath+0x16/0x1b
      Reported-by: default avatarRoland Dreier <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  15. 25 May, 2009 1 commit
  16. 17 May, 2009 1 commit
    • Theodore Ts'o's avatar
      ext4: Add a comprehensive block validity check to ext4_get_blocks() · 6fd058f7
      Theodore Ts'o authored
      To catch filesystem bugs or corruption which could lead to the
      filesystem getting severly damaged, this patch adds a facility for
      tracking all of the filesystem metadata blocks by contiguous regions
      in a red-black tree.  This allows quick searching of the tree to
      locate extents which might overlap with filesystem metadata blocks.
      This facility is also used by the multi-block allocator to assure that
      it is not allocating blocks out of the system zone, as well as by the
      routines used when reading indirect blocks and extents information
      from disk to make sure their contents are valid.
      Signed-off-by: default avatar"Theodore Ts'o" <>
  17. 14 May, 2009 3 commits
  18. 12 May, 2009 1 commit
  19. 13 May, 2009 1 commit
  20. 12 May, 2009 1 commit
  21. 14 May, 2009 3 commits
    • Theodore Ts'o's avatar
      ext4: Add documentation to the ext4_*get_block* functions · b920c755
      Theodore Ts'o authored
      This adds more documentation to various internal functions in
      fs/ext4/inode.c, most notably ext4_ind_get_blocks(),
      ext4_da_get_block_write(), ext4_da_get_block_prep(),
      In addition, the static function ext4_normal_get_block_write() has
      been renamed noalloc_get_block_write(), since it is used in many
      places far beyond ext4_normal_writepage().
      Plenty of warnings have been added to the noalloc_get_block_write()
      function, since the way it is used is amazingly fragile.
      Signed-off-by: default avatar"Theodore Ts'o" <>
    • Theodore Ts'o's avatar
      ext4: Define a new set of flags for ext4_get_blocks() · c2177057
      Theodore Ts'o authored
      The functions ext4_get_blocks(), ext4_ext_get_blocks(), and
      ext4_ind_get_blocks() used an ad-hoc set of integer variables used as
      boolean flags passed in as arguments.  Use a single flags parameter
      and a setandard set of bitfield flags instead.  This saves space on
      the call stack, and it also makes the code a bit more understandable.
      Signed-off-by: default avatar"Theodore Ts'o" <>
    • Theodore Ts'o's avatar
      ext4: Rename ext4_get_blocks_wrap() to be ext4_get_blocks() · 12b7ac17
      Theodore Ts'o authored
      Another function rename for clarity's sake.  The _wrap prefix simply
      confuses people, and didn't add much people trying to follow the code
      Signed-off-by: default avatar"Theodore Ts'o" <>
  22. 12 May, 2009 2 commits
  23. 17 Jun, 2009 1 commit
  24. 01 May, 2009 1 commit
    • Theodore Ts'o's avatar
      ext4: Avoid races caused by on-line resizing and SMP memory reordering · 8df9675f
      Theodore Ts'o authored
      Ext4's on-line resizing adds a new block group and then, only at the
      last step adjusts s_groups_count.  However, it's possible on SMP
      systems that another CPU could see the updated the s_group_count and
      not see the newly initialized data structures for the just-added block
      group.  For this reason, it's important to insert a SMP read barrier
      after reading s_groups_count and before reading any (for example) the
      new block group descriptors allowed by the increased value of
      Unfortunately, we rather blatently violate this locking protocol
      documented in fs/ext4/resize.c.  Fortunately, (1) on-line resizes
      happen relatively rarely, and (2) it seems rare that the filesystem
      code will immediately try to use just-added block group before any
      memory ordering issues resolve themselves.  So apparently problems
      here are relatively hard to hit, since ext3 has been vulnerable to the
      same issue for years with no one apparently complaining.
      Signed-off-by: default avatar"Theodore Ts'o" <>
  25. 12 May, 2009 1 commit
    • Aneesh Kumar K.V's avatar
      ext4: Mark the unwritten buffer_head as mapped during write_begin · 29fa89d0
      Aneesh Kumar K.V authored
      Setting BH_Unwritten buffer_heads as BH_Mapped avoids multiple
      (unnecessary) calls to get_block() during the call to the write(2)
      system call.  Setting BH_Unwritten buffer heads as BH_Mapped requires
      that the writepages() functions can handle BH_Unwritten buffer_heads.
      After this commit, things work as follows:
      ext4_ext_get_block() returns unmapped, unwritten, buffer head when
      called with create = 0 for prealloc space. This makes sure we handle
      the read path and non-delayed allocation case correctly.  Even though
      the buffer head is marked unmapped we have valid b_blocknr and b_bdev
      values in the buffer_head.
      ext4_da_get_block_prep() called for block resrevation will now return
      mapped, unwritten, new buffer_head for prealloc space. This avoids
      multiple calls to get_block() for write to same offset. By making such
      buffers as BH_New, we also assure that sub-block zeroing of buffered
      writes happens correctly.
      Signed-off-by: default avatarAneesh Kumar K.V <>
      Signed-off-by: default avatar"Theodore Ts'o" <>
  26. 13 May, 2009 1 commit
  27. 24 Apr, 2009 3 commits
    • Theodore Ts'o's avatar
      ext4: Do not try to validate extents on special files · c4b5a614
      Theodore Ts'o authored
      The EXTENTS_FL flag should never be set on special files, but if it
      is, don't bother trying to validate that the extents tree is valid,
      since only files, directories, and non-fast symlinks will ever have an
      extent data structure.  We perhaps should flag the filesystem as being
      corrupted if we see a special file (named pipes, device nodes, Unix
      domain sockets, etc.) with the EXTENTS_FL flag, but e2fsck doesn't
      currently check this case, so we'll just ignore this for now, since
      it's harmless.
      Without this fix, a special device with the extents flag is flagged as
      an error by the kernel, so it is impossible to access or delete the
      inode, but e2fsck doesn't see it as a problem, leading to
      confused/frustrated users.
      Signed-off-by: default avatar"Theodore Ts'o" <>
    • Theodore Ts'o's avatar
      ext4: Ignore i_file_acl_high unless EXT4_FEATURE_INCOMPAT_64BIT is present · a9e81742
      Theodore Ts'o authored
      Don't try to look at i_file_acl_high unless the INCOMPAT_64BIT feature
      bit is set.  The field is normally zero, but older versions of e2fsck
      didn't automatically check to make sure of this, so in the spirit of
      "be liberal in what you accept", don't look at i_file_acl_high unless
      we are using a 64-bit filesystem.
      Signed-off-by: default avatar"Theodore Ts'o" <>
    • Theodore Ts'o's avatar
      ext4: Fix softlockup caused by illegal i_file_acl value in on-disk inode · 485c26ec
      Theodore Ts'o authored
      If the block containing external extended attributes (which is stored
      in i_file_acl and i_file_acl_high) is larger than the on-disk
      filesystem, the process which tried to access the extended attributes
      will endlessly issue kernel printks complaining that
      "__find_get_block_slow() failed", locking up that CPU until the system
      is forcibly rebooted.
      So when we read in the inode, make sure the i_file_acl value is legal,
      and if not, flag the filesystem as being corrupted.
      Signed-off-by: default avatar"Theodore Ts'o" <>
  28. 07 Apr, 2009 1 commit