1. 11 7月, 2013 2 次提交
  2. 10 5月, 2013 1 次提交
    • M
      dm bufio: avoid a possible __vmalloc deadlock · 502624bd
      Mikulas Patocka 提交于
      This patch uses memalloc_noio_save to avoid a possible deadlock in
      dm-bufio.  (it could happen only with large block size, at most
      PAGE_SIZE << MAX_ORDER (typically 8MiB).
      
      __vmalloc doesn't fully respect gfp flags. The specified gfp flags are
      used for allocation of requested pages, structures vmap_area, vmap_block
      and vm_struct and the radix tree nodes.
      
      However, the kernel pagetables are allocated always with GFP_KERNEL.
      Thus the allocation of pagetables can recurse back to the I/O layer and
      cause a deadlock.
      
      This patch uses the function memalloc_noio_save to set per-process
      PF_MEMALLOC_NOIO flag and the function memalloc_noio_restore to restore
      it. When this flag is set, all allocations in the process are done with
      implied GFP_NOIO flag, thus the deadlock can't happen.
      
      This should be backported to stable kernels, but they don't have the
      PF_MEMALLOC_NOIO flag and memalloc_noio_save/memalloc_noio_restore
      functions. So, PF_MEMALLOC should be set and restored instead.
      Signed-off-by: NMikulas Patocka <mpatocka@redhat.com>
      Cc: stable@kernel.org
      Signed-off-by: NAlasdair G Kergon <agk@redhat.com>
      502624bd
  3. 21 3月, 2013 1 次提交
    • M
      dm verity: avoid deadlock · 3b6b7813
      Mikulas Patocka 提交于
      A deadlock was found in the prefetch code in the dm verity map
      function.  This patch fixes this by transferring the prefetch
      to a worker thread and skipping it completely if kmalloc fails.
      
      If generic_make_request is called recursively, it queues the I/O
      request on the current->bio_list without making the I/O request
      and returns. The routine making the recursive call cannot wait
      for the I/O to complete.
      
      The deadlock occurs when one thread grabs the bufio_client
      mutex and waits for an I/O to complete but the I/O is queued
      on another thread's current->bio_list and is waiting to get
      the mutex held by the first thread.
      
      The fix recognises that prefetching is not essential.  If memory
      can be allocated, it queues the prefetch request to the worker thread,
      but if not, it does nothing.
      Signed-off-by: NPaul Taysom <taysom@chromium.org>
      Signed-off-by: NMikulas Patocka <mpatocka@redhat.com>
      Signed-off-by: NAlasdair G Kergon <agk@redhat.com>
      Cc: stable@kernel.org
      3b6b7813
  4. 02 3月, 2013 1 次提交
  5. 28 2月, 2013 1 次提交
    • S
      hlist: drop the node parameter from iterators · b67bfe0d
      Sasha Levin 提交于
      I'm not sure why, but the hlist for each entry iterators were conceived
      
              list_for_each_entry(pos, head, member)
      
      The hlist ones were greedy and wanted an extra parameter:
      
              hlist_for_each_entry(tpos, pos, head, member)
      
      Why did they need an extra pos parameter? I'm not quite sure. Not only
      they don't really need it, it also prevents the iterator from looking
      exactly like the list iterator, which is unfortunate.
      
      Besides the semantic patch, there was some manual work required:
      
       - Fix up the actual hlist iterators in linux/list.h
       - Fix up the declaration of other iterators based on the hlist ones.
       - A very small amount of places were using the 'node' parameter, this
       was modified to use 'obj->member' instead.
       - Coccinelle didn't handle the hlist_for_each_entry_safe iterator
       properly, so those had to be fixed up manually.
      
      The semantic patch which is mostly the work of Peter Senna Tschudin is here:
      
      @@
      iterator name hlist_for_each_entry, hlist_for_each_entry_continue, hlist_for_each_entry_from, hlist_for_each_entry_rcu, hlist_for_each_entry_rcu_bh, hlist_for_each_entry_continue_rcu_bh, for_each_busy_worker, ax25_uid_for_each, ax25_for_each, inet_bind_bucket_for_each, sctp_for_each_hentry, sk_for_each, sk_for_each_rcu, sk_for_each_from, sk_for_each_safe, sk_for_each_bound, hlist_for_each_entry_safe, hlist_for_each_entry_continue_rcu, nr_neigh_for_each, nr_neigh_for_each_safe, nr_node_for_each, nr_node_for_each_safe, for_each_gfn_indirect_valid_sp, for_each_gfn_sp, for_each_host;
      
      type T;
      expression a,c,d,e;
      identifier b;
      statement S;
      @@
      
      -T b;
          <+... when != b
      (
      hlist_for_each_entry(a,
      - b,
      c, d) S
      |
      hlist_for_each_entry_continue(a,
      - b,
      c) S
      |
      hlist_for_each_entry_from(a,
      - b,
      c) S
      |
      hlist_for_each_entry_rcu(a,
      - b,
      c, d) S
      |
      hlist_for_each_entry_rcu_bh(a,
      - b,
      c, d) S
      |
      hlist_for_each_entry_continue_rcu_bh(a,
      - b,
      c) S
      |
      for_each_busy_worker(a, c,
      - b,
      d) S
      |
      ax25_uid_for_each(a,
      - b,
      c) S
      |
      ax25_for_each(a,
      - b,
      c) S
      |
      inet_bind_bucket_for_each(a,
      - b,
      c) S
      |
      sctp_for_each_hentry(a,
      - b,
      c) S
      |
      sk_for_each(a,
      - b,
      c) S
      |
      sk_for_each_rcu(a,
      - b,
      c) S
      |
      sk_for_each_from
      -(a, b)
      +(a)
      S
      + sk_for_each_from(a) S
      |
      sk_for_each_safe(a,
      - b,
      c, d) S
      |
      sk_for_each_bound(a,
      - b,
      c) S
      |
      hlist_for_each_entry_safe(a,
      - b,
      c, d, e) S
      |
      hlist_for_each_entry_continue_rcu(a,
      - b,
      c) S
      |
      nr_neigh_for_each(a,
      - b,
      c) S
      |
      nr_neigh_for_each_safe(a,
      - b,
      c, d) S
      |
      nr_node_for_each(a,
      - b,
      c) S
      |
      nr_node_for_each_safe(a,
      - b,
      c, d) S
      |
      - for_each_gfn_sp(a, c, d, b) S
      + for_each_gfn_sp(a, c, d) S
      |
      - for_each_gfn_indirect_valid_sp(a, c, d, b) S
      + for_each_gfn_indirect_valid_sp(a, c, d) S
      |
      for_each_host(a,
      - b,
      c) S
      |
      for_each_host_safe(a,
      - b,
      c, d) S
      |
      for_each_mesh_entry(a,
      - b,
      c, d) S
      )
          ...+>
      
      [akpm@linux-foundation.org: drop bogus change from net/ipv4/raw.c]
      [akpm@linux-foundation.org: drop bogus hunk from net/ipv6/raw.c]
      [akpm@linux-foundation.org: checkpatch fixes]
      [akpm@linux-foundation.org: fix warnings]
      [akpm@linux-foudnation.org: redo intrusive kvm changes]
      Tested-by: NPeter Senna Tschudin <peter.senna@gmail.com>
      Acked-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      Signed-off-by: NSasha Levin <sasha.levin@oracle.com>
      Cc: Wu Fengguang <fengguang.wu@intel.com>
      Cc: Marcelo Tosatti <mtosatti@redhat.com>
      Cc: Gleb Natapov <gleb@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      b67bfe0d
  6. 12 10月, 2012 2 次提交
  7. 29 3月, 2012 1 次提交
  8. 04 2月, 2012 1 次提交
  9. 08 11月, 2011 1 次提交
  10. 01 11月, 2011 1 次提交
    • M
      dm: add bufio · 95d402f0
      Mikulas Patocka 提交于
      The dm-bufio interface allows you to do cached I/O on devices,
      holding recently-read blocks in memory and performing delayed writes.
      
      We don't use buffer cache or page cache already present in the kernel, because:
      * we need to handle block sizes larger than a page
      * we can't allocate memory to perform reads or we'd have deadlocks
      
      Currently, when a cache is required, we limit its size to a fraction of
      available memory.  Usage can be viewed and changed in
      /sys/module/dm_bufio/parameters/ .
      
      The first user is thin provisioning, but more dm users are planned.
      Signed-off-by: NMikulas Patocka <mpatocka@redhat.com>
      Signed-off-by: NAlasdair G Kergon <agk@redhat.com>
      95d402f0