1. 03 2月, 2010 11 次提交
    • T
      idr: fix a critical misallocation bug · 859ddf09
      Tejun Heo 提交于
      Eric Paris located a bug in idr.  With IDR_BITS of 6, it grows to three
      layers when id 4096 is first allocated.  When that happens, idr wraps
      incorrectly and searches the idr array ignoring the high bits.  The
      following test code from Eric demonstrates the bug nicely.
      
      #include <linux/idr.h>
      #include <linux/kernel.h>
      #include <linux/module.h>
      
      static DEFINE_IDR(test_idr);
      
      int init_module(void)
      {
      	int ret, forty95, forty96;
      	void *addr;
      
      	/* add 2 entries both with 4095 as the start address */
      again1:
      	if (!idr_pre_get(&test_idr, GFP_KERNEL))
      		return -ENOMEM;
      	ret = idr_get_new_above(&test_idr, (void *)4095, 4095, &forty95);
      	if (ret) {
      		if (ret == -EAGAIN)
      			goto again1;
      		return ret;
      	}
      	if (forty95 != 4095)
      		printk(KERN_ERR "hmmm, forty95=%d\n", forty95);
      
      again2:
      	if (!idr_pre_get(&test_idr, GFP_KERNEL))
      		return -ENOMEM;
      	ret = idr_get_new_above(&test_idr, (void *)4096, 4095, &forty96);
      	if (ret) {
      		if (ret == -EAGAIN)
      			goto again2;
      		return ret;
      	}
      	if (forty96 != 4096)
      		printk(KERN_ERR "hmmm, forty96=%d\n", forty96);
      
      	/* try to find the 2 entries, noticing that 4096 broke */
      	addr = idr_find(&test_idr, forty95);
      	if ((int)addr != forty95)
      		printk(KERN_ERR "hmmm, after find forty95=%d addr=%d\n", forty95, (int)addr);
      	addr = idr_find(&test_idr, forty96);
      	if ((int)addr != forty96)
      		printk(KERN_ERR "hmmm, after find forty96=%d addr=%d\n", forty96, (int)addr);
      	/* really weird, the entry which should be at 4096 is actually at 0!! */
      	addr = idr_find(&test_idr, 0);
      	if ((int)addr)
      		printk(KERN_ERR "found an entry at id=0 for addr=%d\n", (int)addr);
      
      	idr_remove(&test_idr, forty95);
      	idr_remove(&test_idr, forty96);
      
      	return 0;
      }
      
      void cleanup_module(void)
      {
      }
      
      MODULE_AUTHOR("Eric Paris <eparis@redhat.com>");
      MODULE_DESCRIPTION("Simple idr test");
      MODULE_LICENSE("GPL");
      
      This happens because when sub_alloc() back tracks it doesn't always do it
      step-by-step while the over-the-limit detection assumes step-by-step
      backtracking.  The logic in sub_alloc() looks like the following.
      
        restart:
          clear pa[top level + 1] for end cond detection
          l = top level
          while (true) {
      	search for empty slot at this level
      	if (not found) {
      	    push id to the next possible value
      	    l++
      A:	    if (pa[l] is clear)
      	        failed, return asking caller to grow the tree
      	    if (going up 1 level gives more slots to search)
      	        continue the while loop above with the incremented l
      	    else
      C:	        goto restart
      	}
      	adjust id accordingly to the found slot
      	if (l == 0)
      	    return found id;
      	create lower level if not there yet
      	record pa[l] and l--
          }
      
      Test A is the fail exit condition but this assumes that failure is
      propagated upwared one level at a time but the B optimization path breaks
      the assumption and restarts the whole thing with a start value which is
      above the possible limit with the current layers.  sub_alloc() assumes the
      start id value is inside the limit when called and test A is the only exit
      condition check, so it ends up searching for empty slot while ignoring
      high set bit.
      
      So, for 4095->4096 test, level0 search fails but pa[1] contains a valid
      pointer.  However, going up 1 level wouldn't give any more empty slot so
      it takes C and when the whole thing restarts nobody notices the high bit
      set beyond the top level.
      
      This patch fixes the bug by changing the fail exit condition check to full
      id limit check.
      
      Based-on-patch-from: Eric Paris <eparis@redhat.com>
      Reported-by: NEric Paris <eparis@redhat.com>
      Signed-off-by: NTejun Heo <tj@kernel.org>
      Cc: <stable@kernel.org>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      859ddf09
    • L
      Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block · 1a45dcfe
      Linus Torvalds 提交于
      * 'for-linus' of git://git.kernel.dk/linux-2.6-block:
        cfq-iosched: Do not idle on async queues
        blk-cgroup: Fix potential deadlock in blk-cgroup
        block: fix bugs in bio-integrity mempool usage
        block: fix bio_add_page for non trivial merge_bvec_fn case
        drbd: null dereference bug
        drbd: fix max_segment_size initialization
      1a45dcfe
    • N
      mm: purge fragmented percpu vmap blocks · 02b709df
      Nick Piggin 提交于
      Improve handling of fragmented per-CPU vmaps.  We previously don't free
      up per-CPU maps until all its addresses have been used and freed.  So
      fragmented blocks could fill up vmalloc space even if they actually had
      no active vmap regions within them.
      
      Add some logic to allow all CPUs to have these blocks purged in the case
      of failure to allocate a new vm area, and also put some logic to trim
      such blocks of a current CPU if we hit them in the allocation path (so
      as to avoid a large build up of them).
      
      Christoph reported some vmap allocation failures when using the per CPU
      vmap APIs in XFS, which cannot be reproduced after this patch and the
      previous bug fix.
      
      Cc: linux-mm@kvack.org
      Cc: stable@kernel.org
      Tested-by: NChristoph Hellwig <hch@infradead.org>
      Signed-off-by: NNick Piggin <npiggin@suse.de>
      --
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      02b709df
    • N
      mm: percpu-vmap fix RCU list walking · de560423
      Nick Piggin 提交于
      RCU list walking of the per-cpu vmap cache was broken.  It did not use
      RCU primitives, and also the union of free_list and rcu_head is
      obviously wrong (because free_list is indeed the list we are RCU
      walking).
      
      While we are there, remove a couple of unused fields from an earlier
      iteration.
      
      These APIs aren't actually used anywhere, because of problems with the
      XFS conversion.  Christoph has now verified that the problems are solved
      with these patches.  Also it is an exported interface, so I think it
      will be good to be merged now (and Christoph wants to get the XFS
      changes into their local tree).
      
      Cc: stable@kernel.org
      Cc: linux-mm@kvack.org
      Tested-by: NChristoph Hellwig <hch@infradead.org>
      Signed-off-by: NNick Piggin <npiggin@suse.de>
      --
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      de560423
    • L
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 · 489b24f2
      Linus Torvalds 提交于
      * git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
        random: Remove unused inode variable
        crypto: padlock-sha - Add import/export support
        random: drop weird m_time/a_time manipulation
      489b24f2
    • L
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes · 4dab75ec
      Linus Torvalds 提交于
      * git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
        GFS2: Use GFP_NOFS for alloc structure
        GFS2: Fix previous patch
        GFS2: Don't withdraw on partial rindex entries
        GFS2: Fix refcnt leak on gfs2_follow_link() error path
      4dab75ec
    • L
      Merge branch 'sh/for-2.6.33' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6 · 7fbcca25
      Linus Torvalds 提交于
      * 'sh/for-2.6.33' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6:
        sh: Fix access to released memory in clk_debugfs_register_one()
        sh: Fix access to released memory in dwarf_unwinder_cleanup()
        usb: r8a66597-hdc disable interrupts fix
        spi: spi_sh_msiof: Fixed data sampling on the correct edge
      7fbcca25
    • L
      Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus · e770a0f1
      Linus Torvalds 提交于
      * 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
        MIPS: 64-bit: Detect virtual memory size
        MIPS: AR7: Fix USB slave mem range typo
        MIPS: Alchemy: Fix dbdma ring destruction memory debugcheck.
      e770a0f1
    • L
      Fix 'flush_old_exec()/setup_new_exec()' split · 7ab02af4
      Linus Torvalds 提交于
      Commit 221af7f8 ("Split 'flush_old_exec' into two functions") split
      the function at the point of no return - ie right where there were no
      more error cases to check.  That made sense from a technical standpoint,
      but when we then also combined it with the actual personality setting
      going in between flush_old_exec() and setup_new_exec(), it needs to be a
      bit more careful.
      
      In particular, we need to make sure that we really flush the old
      personality bits in the 'flush' stage, rather than later in the 'setup'
      stage, since otherwise we might be flushing the _new_ personality state
      that we're just setting up.
      
      So this moves the flags and personality flushing (and 'flush_thread()',
      which is the arch-specific function that generally resets lazy FP state
      etc) of the old process into flush_old_exec(), so that it doesn't affect
      any state that execve() is setting up for the new process environment.
      
      This was reported by Michal Simek as breaking his Microblaze qemu
      environment.
      Reported-and-tested-by: NMichal Simek <michal.simek@petalogix.com>
      Cc: Peter Anvin <hpa@zytor.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      7ab02af4
    • V
      cfq-iosched: Do not idle on async queues · 1efe8fe1
      Vivek Goyal 提交于
      Few weeks back, Shaohua Li had posted similar patch. I am reposting it
      with more test results.
      
      This patch does two things.
      
      - Do not idle on async queues.
      
      - It also changes the write queue depth CFQ drives (cfq_may_dispatch()).
        Currently, we seem to driving queue depth of 1 always for WRITES. This is
        true even if there is only one write queue in the system and all the logic
        of infinite queue depth in case of single busy queue as well as slowly
        increasing queue depth based on last delayed sync request does not seem to
        be kicking in at all.
      
      This patch will allow deeper WRITE queue depths (subjected to the other
      WRITE queue depth contstraints like cfq_quantum and last delayed sync
      request).
      
      Shaohua Li had reported getting more out of his SSD. For me, I have got
      one Lun exported from an HP EVA and when pure buffered writes are on, I
      can get more out of the system. Following are test results of pure
      buffered writes (with end_fsync=1) with vanilla and patched kernel. These
      results are average of 3 sets of run with increasing number of threads.
      
      AVERAGE[bufwfs][vanilla]
      -------
      job       Set NR  ReadBW(KB/s)   MaxClat(us)    WriteBW(KB/s)  MaxClat(us)
      ---       --- --  ------------   -----------    -------------  -----------
      bufwfs    3   1   0              0              95349          474141
      bufwfs    3   2   0              0              100282         806926
      bufwfs    3   4   0              0              109989         2.7301e+06
      bufwfs    3   8   0              0              116642         3762231
      bufwfs    3   16  0              0              118230         6902970
      
      AVERAGE[bufwfs] [patched kernel]
      -------
      bufwfs    3   1   0              0              270722         404352
      bufwfs    3   2   0              0              206770         1.06552e+06
      bufwfs    3   4   0              0              195277         1.62283e+06
      bufwfs    3   8   0              0              260960         2.62979e+06
      bufwfs    3   16  0              0              299260         1.70731e+06
      
      I also ran buffered writes along with some sequential reads and some
      buffered reads going on in the system on a SATA disk because the potential
      risk could be that we should not be driving queue depth higher in presence
      of sync IO going to keep the max clat low.
      
      With some random and sequential reads going on in the system on one SATA
      disk I did not see any significant increase in max clat. So it looks like
      other WRITE queue depth control logic is doing its job. Here are the
      results.
      
      AVERAGE[brr, bsr, bufw together] [vanilla]
      -------
      job       Set NR  ReadBW(KB/s)   MaxClat(us)    WriteBW(KB/s)  MaxClat(us)
      ---       --- --  ------------   -----------    -------------  -----------
      brr       3   1   850            546345         0              0
      bsr       3   1   14650          729543         0              0
      bufw      3   1   0              0              23908          8274517
      
      brr       3   2   981.333        579395         0              0
      bsr       3   2   14149.7        1175689        0              0
      bufw      3   2   0              0              21921          1.28108e+07
      
      brr       3   4   898.333        1.75527e+06    0              0
      bsr       3   4   12230.7        1.40072e+06    0              0
      bufw      3   4   0              0              19722.3        2.4901e+07
      
      brr       3   8   900            3160594        0              0
      bsr       3   8   9282.33        1.91314e+06    0              0
      bufw      3   8   0              0              18789.3        23890622
      
      AVERAGE[brr, bsr, bufw mixed] [patched kernel]
      -------
      job       Set NR  ReadBW(KB/s)   MaxClat(us)    WriteBW(KB/s)  MaxClat(us)
      ---       --- --  ------------   -----------    -------------  -----------
      brr       3   1   837            417973         0              0
      bsr       3   1   14357.7        591275         0              0
      bufw      3   1   0              0              24869.7        8910662
      
      brr       3   2   1038.33        543434         0              0
      bsr       3   2   13351.3        1205858        0              0
      bufw      3   2   0              0              18626.3        13280370
      
      brr       3   4   913            1.86861e+06    0              0
      bsr       3   4   12652.3        1430974        0              0
      bufw      3   4   0              0              15343.3        2.81305e+07
      
      brr       3   8   890            2.92695e+06    0              0
      bsr       3   8   9635.33        1.90244e+06    0              0
      bufw      3   8   0              0              17200.3        24424392
      
      So looks like it might make sense to include this patch.
      
      Thanks
      Vivek
      Signed-off-by: NVivek Goyal <vgoyal@redhat.com>
      Signed-off-by: NJens Axboe <jens.axboe@oracle.com>
      1efe8fe1
    • G
      MIPS: 64-bit: Detect virtual memory size · 91dfc423
      Guenter Roeck 提交于
      Linux kernel 2.6.32 and later allocate address space from the top of the
      kernel virtual memory address space.
      
      This patch implements virtual memory size detection for 64 bit MIPS CPUs
      to avoid resulting crashes.
      Signed-off-by: NGuenter Roeck <guenter.roeck@ericsson.com>
      Cc: linux-mips@linux-mips.org
      Patchwork: http://patchwork.linux-mips.org/patch/935/Reviewed-by: NDavid Daney <ddaney@caviumnetworks.com>
      Signed-off-by: NRalf Baechle <ralf@linux-mips.org>
      91dfc423
  2. 02 2月, 2010 20 次提交
  3. 01 2月, 2010 9 次提交
    • M
      regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints · a2fad9bf
      Mark Brown 提交于
      The WM8350 LED driver needs to be able to enable and disable the
      regulators it is using. Previously the core wasn't properly enforcing
      status change constraints so the driver was able to function but this
      has always been intended to be required.
      Signed-off-by: NMark Brown <broonie@opensource.wolfsonmicro.com>
      Cc: stable@kernel.org
      Signed-off-by: NLiam Girdwood <lrg@slimlogic.co.uk>
      a2fad9bf
    • S
      GFS2: Use GFP_NOFS for alloc structure · ea8d62da
      Steven Whitehouse 提交于
      This is called under a glock, so its a good plan to use GFP_NOFS
      Signed-off-by: NSteven Whitehouse <swhiteho@redhat.com>
      ea8d62da
    • S
      GFS2: Fix previous patch · 7fe3ec6f
      Steven Whitehouse 提交于
      The do_div() call needs to remain.
      Signed-off-by: NSteven Whitehouse <swhiteho@redhat.com>
      7fe3ec6f
    • B
      GFS2: Don't withdraw on partial rindex entries · 55f0b4c5
      Benjamin Marzinski 提交于
      ince gfs2 writes the rindex file a block at a time, and releases the
      exclusive lock after each block, it is possible that another process
      will grab the lock in the middle of the write.  Since rindex entries are
      not an even divisor of blocks, that other process may see partial
      entries.  On grows, this is fine.  The process can simply ignore the the
      partial entires. Previously, the code withdrew when it saw partial
      entries. Now it simply ignores them.
      Signed-off-by: NBenjamin Marzinski <bmarzins@redhat.com>
      Signed-off-by: NSteven Whitehouse <swhiteho@redhat.com>
      55f0b4c5
    • G
      blk-cgroup: Fix potential deadlock in blk-cgroup · bcf4dd43
      Gui Jianfeng 提交于
      I triggered a lockdep warning as following.
      
      =======================================================
      [ INFO: possible circular locking dependency detected ]
      2.6.33-rc2 #1
      -------------------------------------------------------
      test_io_control/7357 is trying to acquire lock:
       (blkio_list_lock){+.+...}, at: [<c053a990>] blkiocg_weight_write+0x82/0x9e
      
      but task is already holding lock:
       (&(&blkcg->lock)->rlock){......}, at: [<c053a949>] blkiocg_weight_write+0x3b/0x9e
      
      which lock already depends on the new lock.
      
      the existing dependency chain (in reverse order) is:
      
      -> #2 (&(&blkcg->lock)->rlock){......}:
             [<c04583b7>] validate_chain+0x8bc/0xb9c
             [<c0458dba>] __lock_acquire+0x723/0x789
             [<c0458eb0>] lock_acquire+0x90/0xa7
             [<c0692b0a>] _raw_spin_lock_irqsave+0x27/0x5a
             [<c053a4e1>] blkiocg_add_blkio_group+0x1a/0x6d
             [<c053cac7>] cfq_get_queue+0x225/0x3de
             [<c053eec2>] cfq_set_request+0x217/0x42d
             [<c052c8a6>] elv_set_request+0x17/0x26
             [<c0532a0f>] get_request+0x203/0x2c5
             [<c0532ae9>] get_request_wait+0x18/0x10e
             [<c0533470>] __make_request+0x2ba/0x375
             [<c0531985>] generic_make_request+0x28d/0x30f
             [<c0532da7>] submit_bio+0x8a/0x8f
             [<c04d827a>] submit_bh+0xf0/0x10f
             [<c04d91d2>] ll_rw_block+0xc0/0xf9
             [<f86e9705>] ext3_find_entry+0x319/0x544 [ext3]
             [<f86eae58>] ext3_lookup+0x2c/0xb9 [ext3]
             [<c04c3e1b>] do_lookup+0xd3/0x172
             [<c04c56c8>] link_path_walk+0x5fb/0x95c
             [<c04c5a65>] path_walk+0x3c/0x81
             [<c04c5b63>] do_path_lookup+0x21/0x8a
             [<c04c66cc>] do_filp_open+0xf0/0x978
             [<c04c0c7e>] open_exec+0x1b/0xb7
             [<c04c1436>] do_execve+0xbb/0x266
             [<c04081a9>] sys_execve+0x24/0x4a
             [<c04028a2>] ptregs_execve+0x12/0x18
      
      -> #1 (&(&q->__queue_lock)->rlock){..-.-.}:
             [<c04583b7>] validate_chain+0x8bc/0xb9c
             [<c0458dba>] __lock_acquire+0x723/0x789
             [<c0458eb0>] lock_acquire+0x90/0xa7
             [<c0692b0a>] _raw_spin_lock_irqsave+0x27/0x5a
             [<c053dd2a>] cfq_unlink_blkio_group+0x17/0x41
             [<c053a6eb>] blkiocg_destroy+0x72/0xc7
             [<c0467df0>] cgroup_diput+0x4a/0xb2
             [<c04ca473>] dentry_iput+0x93/0xb7
             [<c04ca4b3>] d_kill+0x1c/0x36
             [<c04cb5c5>] dput+0xf5/0xfe
             [<c04c6084>] do_rmdir+0x95/0xbe
             [<c04c60ec>] sys_rmdir+0x10/0x12
             [<c04027cc>] sysenter_do_call+0x12/0x32
      
      -> #0 (blkio_list_lock){+.+...}:
             [<c0458117>] validate_chain+0x61c/0xb9c
             [<c0458dba>] __lock_acquire+0x723/0x789
             [<c0458eb0>] lock_acquire+0x90/0xa7
             [<c06929fd>] _raw_spin_lock+0x1e/0x4e
             [<c053a990>] blkiocg_weight_write+0x82/0x9e
             [<c0467f1e>] cgroup_file_write+0xc6/0x1c0
             [<c04bd2f3>] vfs_write+0x8c/0x116
             [<c04bd7c6>] sys_write+0x3b/0x60
             [<c04027cc>] sysenter_do_call+0x12/0x32
      
      other info that might help us debug this:
      
      1 lock held by test_io_control/7357:
       #0:  (&(&blkcg->lock)->rlock){......}, at: [<c053a949>] blkiocg_weight_write+0x3b/0x9e
      stack backtrace:
      Pid: 7357, comm: test_io_control Not tainted 2.6.33-rc2 #1
      Call Trace:
       [<c045754f>] print_circular_bug+0x91/0x9d
       [<c0458117>] validate_chain+0x61c/0xb9c
       [<c0458dba>] __lock_acquire+0x723/0x789
       [<c0458eb0>] lock_acquire+0x90/0xa7
       [<c053a990>] ? blkiocg_weight_write+0x82/0x9e
       [<c06929fd>] _raw_spin_lock+0x1e/0x4e
       [<c053a990>] ? blkiocg_weight_write+0x82/0x9e
       [<c053a990>] blkiocg_weight_write+0x82/0x9e
       [<c0467f1e>] cgroup_file_write+0xc6/0x1c0
       [<c0454df5>] ? trace_hardirqs_off+0xb/0xd
       [<c044d93a>] ? cpu_clock+0x2e/0x44
       [<c050e6ec>] ? security_file_permission+0xf/0x11
       [<c04bcdda>] ? rw_verify_area+0x8a/0xad
       [<c0467e58>] ? cgroup_file_write+0x0/0x1c0
       [<c04bd2f3>] vfs_write+0x8c/0x116
       [<c04bd7c6>] sys_write+0x3b/0x60
       [<c04027cc>] sysenter_do_call+0x12/0x32
      
      To prevent deadlock, we should take locks as following sequence:
      
      blkio_list_lock -> queue_lock ->  blkcg_lock.
      
      The following patch should fix this bug.
      Signed-off-by: NGui Jianfeng <guijianfeng@cn.fujitsu.com>
      Signed-off-by: NJens Axboe <jens.axboe@oracle.com>
      bcf4dd43
    • A
      powerpc: TIF_ABI_PENDING bit removal · 94f28da8
      Andreas Schwab 提交于
      Here are the powerpc bits to remove TIF_ABI_PENDING now that
      set_personality() is called at the appropriate place in exec.
      Signed-off-by: NAndreas Schwab <schwab@linux-m68k.org>
      Signed-off-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
      94f28da8
    • M
      drm/radeon/kms: Fix oops after radeon_cs_parser_init() failure. · 17aafcca
      Michel Dänzer 提交于
      If radeon_cs_parser_init() fails, radeon_cs_ioctl() calls
      radeon_cs_parser_fini() with the non-zero error value. The latter dereferenced
      parser->ib which hasn't been initialized yet -> boom. Add a test for parser->ib
      being non-NULL before dereferencing it.
      Signed-off-by: NMichel Dänzer <daenzer@vmware.com>
      Signed-off-by: NDave Airlie <airlied@redhat.com>
      17aafcca
    • B
      powerpc/pseries: Fix xics build without CONFIG_SMP · bf647faf
      Benjamin Herrenschmidt 提交于
      desc->affinity doesn't exit in that case. Let's use a macro for
      the UP variant of get_irq_server(), it's the easiest way, avoids
      evaluating arguments.
      Signed-off-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
      bf647faf
    • D
      drm/radeon/kms: move radeon KMS on/off switch out of staging. · f71d0187
      Dave Airlie 提交于
      We are happy enough that the KMS driver is stable enough for enough people
      for the kms enable/disable to leave staging. Distros can now contemplate
      turning this on.
      Signed-off-by: NDave Airlie <airlied@redhat.com>
      f71d0187