1. 08 Aug, 2011 36 commits
  2. 13 Jul, 2011 4 commits
    • Greg Kroah-Hartman's avatar
      Linux 2.6.32.43 · d0a11cb1
      Greg Kroah-Hartman authored
      d0a11cb1
    • Miklos Szeredi's avatar
      mm: prevent concurrent unmap_mapping_range() on the same inode · ffdd12ea
      Miklos Szeredi authored
      commit 2aa15890 upstream.
      
      Michael Leun reported that running parallel opens on a fuse filesystem
      can trigger a "kernel BUG at mm/truncate.c:475"
      
      Gurudas Pai reported the same bug on NFS.
      
      The reason is, unmap_mapping_range() is not prepared for more than
      one concurrent invocation per inode.  For example:
      
        thread1: going through a big range, stops in the middle of a vma and
           stores the restart address in vm_truncate_count.
      
        thread2: comes in with a small (e.g. single page) unmap request on
           the same vma, somewhere before restart_address, finds that the
           vma was already unmapped up to the restart address and happily
           returns without doing anything.
      
      Another scenario would be two big unmap requests, both having to
      restart the unmapping and each one setting vm_truncate_count to its
      own value.  This could go on forever without any of them being able to
      finish.
      
      Truncate and hole punching already serialize with i_mutex.  Other
      callers of unmap_mapping_range() do not, and it's difficult to get
      i_mutex protection for all callers.  In particular ->d_revalidate(),
      which calls invalidate_inode_pages2_range() in fuse, may be called
      with or without i_mutex.
      
      This patch adds a new mutex to 'struct address_space' to prevent
      running multiple concurrent unmap_mapping_range() on the same mapping.
      
      [ We'll hopefully get rid of all this with the upcoming mm
        preemptibility series by Peter Zijlstra, the "mm: Remove i_mmap_mutex
        lockbreak" patch in particular.  But that is for 2.6.39 ]
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      Reported-by: default avatarMichael Leun <lkml20101129@newton.leun.net>
      Reported-by: default avatarGurudas Pai <gurudas.pai@oracle.com>
      Tested-by: default avatarGurudas Pai <gurudas.pai@oracle.com>
      Acked-by: default avatarHugh Dickins <hughd@google.com>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
      ffdd12ea
    • Xufeng Zhang's avatar
      udp/recvmsg: Clear MSG_TRUNC flag when starting over for a new packet · 453d61c4
      Xufeng Zhang authored
      [ Upstream commit 9cfaa8de ]
      
      Consider this scenario: When the size of the first received udp packet
      is bigger than the receive buffer, MSG_TRUNC bit is set in msg->msg_flags.
      However, if checksum error happens and this is a blocking socket, it will
      goto try_again loop to receive the next packet.  But if the size of the
      next udp packet is smaller than receive buffer, MSG_TRUNC flag should not
      be set, but because MSG_TRUNC bit is not cleared in msg->msg_flags before
      receive the next packet, MSG_TRUNC is still set, which is wrong.
      
      Fix this problem by clearing MSG_TRUNC flag when starting over for a
      new packet.
      Signed-off-by: default avatarXufeng Zhang <xufeng.zhang@windriver.com>
      Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
      453d61c4
    • Xufeng Zhang's avatar
      ipv6/udp: Use the correct variable to determine non-blocking condition · ac7573b5
      Xufeng Zhang authored
      [ Upstream commit 32c90254 ]
      
      udpv6_recvmsg() function is not using the correct variable to determine
      whether or not the socket is in non-blocking operation, this will lead
      to unexpected behavior when a UDP checksum error occurs.
      
      Consider a non-blocking udp receive scenario: when udpv6_recvmsg() is
      called by sock_common_recvmsg(), MSG_DONTWAIT bit of flags variable in
      udpv6_recvmsg() is cleared by "flags & ~MSG_DONTWAIT" in this call:
      
          err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
                         flags & ~MSG_DONTWAIT, &addr_len);
      
      i.e. with udpv6_recvmsg() getting these values:
      
      	int noblock = flags & MSG_DONTWAIT
      	int flags = flags & ~MSG_DONTWAIT
      
      So, when udp checksum error occurs, the execution will go to
      csum_copy_err, and then the problem happens:
      
          csum_copy_err:
                  ...............
                  if (flags & MSG_DONTWAIT)
                          return -EAGAIN;
                  goto try_again;
                  ...............
      
      But it will always go to try_again as MSG_DONTWAIT has been cleared
      from flags at call time -- only noblock contains the original value
      of MSG_DONTWAIT, so the test should be:
      
                  if (noblock)
                          return -EAGAIN;
      
      This is also consistent with what the ipv4/udp code does.
      Signed-off-by: default avatarXufeng Zhang <xufeng.zhang@windriver.com>
      Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
      ac7573b5