1. 07 1月, 2015 6 次提交
    • P
      rcu: Fix rcu_barrier() race that could result in too-short wait · 41050a00
      Paul E. McKenney 提交于
      The rcu_barrier() no-callbacks check for no-CBs CPUs has race conditions.
      It checks a given CPU's lists of callbacks, and if all three no-CBs lists
      are empty, ignores that CPU.  However, these three lists could potentially
      be empty even when callbacks are present if the check executed just as
      the callbacks were being moved from one list to another.  It turns out
      that recent versions of rcutorture can spot this race.
      
      This commit plugs this hole by consolidating the per-list counts of
      no-CBs callbacks into a single count, which is incremented before
      the corresponding callback is posted and after it is invoked.  Then
      rcu_barrier() checks this single count to reliably determine whether
      the corresponding CPU has no-CBs callbacks.
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      41050a00
    • D
      hotplugcpu: Avoid deadlocks by waking active_writer · 87af9e7f
      David Hildenbrand 提交于
      Commit b2c4623d ("rcu: More on deadlock between CPU hotplug and expedited
      grace periods") introduced another problem that can easily be reproduced by
      starting/stopping cpus in a loop.
      
      E.g.:
        for i in `seq 5000`; do
            echo 1 > /sys/devices/system/cpu/cpu1/online
            echo 0 > /sys/devices/system/cpu/cpu1/online
        done
      
      Will result in:
        INFO: task /cpu_start_stop:1 blocked for more than 120 seconds.
        Call Trace:
        ([<00000000006a028e>] __schedule+0x406/0x91c)
         [<0000000000130f60>] cpu_hotplug_begin+0xd0/0xd4
         [<0000000000130ff6>] _cpu_up+0x3e/0x1c4
         [<0000000000131232>] cpu_up+0xb6/0xd4
         [<00000000004a5720>] device_online+0x80/0xc0
         [<00000000004a57f0>] online_store+0x90/0xb0
        ...
      
      And a deadlock.
      
      Problem is that if the last ref in put_online_cpus() can't get the
      cpu_hotplug.lock the puts_pending count is incremented, but a sleeping
      active_writer might never be woken up, therefore never exiting the loop in
      cpu_hotplug_begin().
      
      This fix removes puts_pending and turns refcount into an atomic variable. We
      also introduce a wait queue for the active_writer, to avoid possible races and
      use-after-free. There is no need to take the lock in put_online_cpus() anymore.
      
      Can't reproduce it with this fix.
      Signed-off-by: NDavid Hildenbrand <dahi@linux.vnet.ibm.com>
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      87af9e7f
    • Y
      rculist: Fix sparse warning · f520c98e
      Ying Xue 提交于
      This fixes the following sparse warnings:
      
      make C=1 CF=-D__CHECK_ENDIAN__ net/ipv6/addrconf.o
      net/ipv6/addrconf.c:3495:9: error: incompatible types in comparison expression (different address spaces)
      net/ipv6/addrconf.c:3495:9: error: incompatible types in comparison expression (different address spaces)
      net/ipv6/addrconf.c:3495:9: error: incompatible types in comparison expression (different address spaces)
      net/ipv6/addrconf.c:3495:9: error: incompatible types in comparison expression (different address spaces)
      
      To silence these spare complaints, an RCU annotation should be added to
      "next" pointer of hlist_node structure through hlist_next_rcu() macro
      when iterating over a hlist with hlist_for_each_entry_continue_rcu_bh().
      
      By the way, this commit also resolves the same error appearing in
      hlist_for_each_entry_continue_rcu().
      Signed-off-by: NYing Xue <ying.xue@windriver.com>
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      f520c98e
    • L
      tiny_rcu: Directly force QS when call_rcu_[bh|sched]() on idle_task · 5f6130fa
      Lai Jiangshan 提交于
      For RCU in UP, context-switch = QS = GP, thus we can force a
      context-switch when any call_rcu_[bh|sched]() is happened on idle_task.
      After doing so, rcu_idle/irq_enter/exit() are useless, so we can simply
      make these functions empty.
      
      More important, this change does not change the functionality logically.
      Note: raise_softirq(RCU_SOFTIRQ)/rcu_sched_qs() in rcu_idle_enter() and
      outmost rcu_irq_exit() will have to wake up the ksoftirqd
      (due to in_interrupt() == 0).
      
      Before this patch		After this patch:
      call_rcu_sched() in idle;	call_rcu_sched() in idle
      				  set resched
      do other stuffs;		do other stuffs
      outmost rcu_irq_exit()		outmost rcu_irq_exit() (empty function)
        (or rcu_idle_enter())		  (or rcu_idle_enter(), also empty function)
      				start to resched. (see above)
        rcu_sched_qs()		rcu_sched_qs()
          QS,and GP and advance cb	  QS,and GP and advance cb
          wake up the ksoftirqd	    wake up the ksoftirqd
            set resched
      resched to ksoftirqd (or other)	resched to ksoftirqd (or other)
      
      These two code patches are almost the same.
      
      Size changed after patched:
      
      size kernel/rcu/tiny-old.o kernel/rcu/tiny-patched.o
         text	   data	    bss	    dec	    hex	filename
         3449	    206	      8	   3663	    e4f	kernel/rcu/tiny-old.o
         2406	    144	      8	   2558	    9fe	kernel/rcu/tiny-patched.o
      Signed-off-by: NLai Jiangshan <laijs@cn.fujitsu.com>
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      5f6130fa
    • P
      rcupdate: Replace smp_read_barrier_depends() with lockless_dereference() · ac59853c
      Pranith Kumar 提交于
      Recently lockless_dereference() was added which can be used in place of
      hard-coding smp_read_barrier_depends(). The following PATCH makes the change.
      Signed-off-by: NPranith Kumar <bobby.prani@gmail.com>
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      ac59853c
    • P
      compiler: Allow 1- and 2-byte smp_load_acquire() and smp_store_release() · 536fa402
      Paul E. McKenney 提交于
      CPUs without single-byte and double-byte loads and stores place some
      "interesting" requirements on concurrent code.  For example (adapted
      from Peter Hurley's test code), suppose we have the following structure:
      
      	struct foo {
      		spinlock_t lock1;
      		spinlock_t lock2;
      		char a; /* Protected by lock1. */
      		char b; /* Protected by lock2. */
      	};
      	struct foo *foop;
      
      Of course, it is common (and good) practice to place data protected
      by different locks in separate cache lines.  However, if the locks are
      rarely acquired (for example, only in rare error cases), and there are
      a great many instances of the data structure, then memory footprint can
      trump false-sharing concerns, so that it can be better to place them in
      the same cache cache line as above.
      
      But if the CPU does not support single-byte loads and stores, a store
      to foop->a will do a non-atomic read-modify-write operation on foop->b,
      which will come as a nasty surprise to someone holding foop->lock2.  So we
      now require CPUs to support single-byte and double-byte loads and stores.
      Therefore, this commit adjusts the definition of __native_word() to allow
      these sizes to be used by smp_load_acquire() and smp_store_release().
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      536fa402
  2. 31 12月, 2014 3 次提交
    • P
      rcu: Fix invoke_rcu_callbacks() comment · 924df8a0
      Paul E. McKenney 提交于
      Despite what the comment says, it is only softirqs that are disabled,
      not interrupts.  This commit therefore fixes the comment.
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      924df8a0
    • A
      rcu: Remove redundant rcu_is_cpu_rrupt_from_idle() from tiny RCU · ca9558a3
      Alexander Gordeev 提交于
      Let's start assuming that something in the idle loop posts a callback,
      and scheduling-clock interrupt occurs:
      
      1. The system is idle and stays that way, no runnable tasks.
      
      2. Scheduling-clock interrupt occurs, rcu_check_callbacks() is called
         as result, which in turn calls rcu_is_cpu_rrupt_from_idle().
      
      3. rcu_is_cpu_rrupt_from_idle() reports the CPU was interrupted from
         idle, which results in rcu_sched_qs() call, which does a
         raise_softirq(RCU_SOFTIRQ).
      
      4. Upon return from interrupt, rcu_irq_exit() is invoked, which calls
         rcu_idle_enter_common(), which in turn calls rcu_sched_qs() again,
         which does another raise_softirq(RCU_SOFTIRQ).
      
      5. The softirq happens shortly and invokes rcu_process_callbacks(),
         which invokes __rcu_process_callbacks().
      
      6. So now callbacks can be invoked. At least they can be if
         ->donetail has been updated. Which it will have been because
         rcu_sched_qs() invokes rcu_qsctr_help().
      
      In the described scenario rcu_sched_qs() and raise_softirq(RCU_SOFTIRQ)
      get called twice in steps 3 and 4. This redundancy could be eliminated
      by removing rcu_is_cpu_rrupt_from_idle() function.
      Signed-off-by: NAlexander Gordeev <agordeev@redhat.com>
      Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      ca9558a3
    • P
      rcu: Make rcu_nmi_enter() handle nesting · 734d1680
      Paul E. McKenney 提交于
      The x86 architecture has multiple types of NMI-like interrupts: real
      NMIs, machine checks, and, for some values of NMI-like, debugging
      and breakpoint interrupts.  These interrupts can nest inside each
      other.  Andy Lutomirski is adding RCU support to these interrupts,
      so rcu_nmi_enter() and rcu_nmi_exit() must now correctly handle nesting.
      
      This commit therefore introduces nesting, using a clever NMI-coordination
      algorithm suggested by Andy.  The trick is to atomically increment
      ->dynticks (if needed) before manipulating ->dynticks_nmi_nesting on entry
      (and, accordingly, after on exit).  In addition, ->dynticks_nmi_nesting
      is incremented by one if ->dynticks was incremented and by two otherwise.
      This means that when rcu_nmi_exit() sees ->dynticks_nmi_nesting equal
      to one, it knows that ->dynticks must be atomically incremented.
      
      This NMI-coordination algorithms has been validated by the following
      Promela model:
      
      ------------------------------------------------------------------------
      
      /*
       * Promela model for Andy Lutomirski's suggested change to rcu_nmi_enter()
       * that allows nesting.
       *
       * This program is free software; you can redistribute it and/or modify
       * it under the terms of the GNU General Public License as published by
       * the Free Software Foundation; either version 2 of the License, or
       * (at your option) any later version.
       *
       * This program is distributed in the hope that it will be useful,
       * but WITHOUT ANY WARRANTY; without even the implied warranty of
       * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       * GNU General Public License for more details.
       *
       * You should have received a copy of the GNU General Public License
       * along with this program; if not, you can access it online at
       * http://www.gnu.org/licenses/gpl-2.0.html.
       *
       * Copyright IBM Corporation, 2014
       *
       * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
       */
      
      byte dynticks_nmi_nesting = 0;
      byte dynticks = 0;
      
      /*
       * Promela verision of rcu_nmi_enter().
       */
      inline rcu_nmi_enter()
      {
      	byte incby;
      	byte tmp;
      
      	incby = BUSY_INCBY;
      	assert(dynticks_nmi_nesting >= 0);
      	if
      	:: (dynticks & 1) == 0 ->
      		atomic {
      			dynticks = dynticks + 1;
      		}
      		assert((dynticks & 1) == 1);
      		incby = 1;
      	:: else ->
      		skip;
      	fi;
      	tmp = dynticks_nmi_nesting;
      	tmp = tmp + incby;
      	dynticks_nmi_nesting = tmp;
      	assert(dynticks_nmi_nesting >= 1);
      }
      
      /*
       * Promela verision of rcu_nmi_exit().
       */
      inline rcu_nmi_exit()
      {
      	byte tmp;
      
      	assert(dynticks_nmi_nesting > 0);
      	assert((dynticks & 1) != 0);
      	if
      	:: dynticks_nmi_nesting != 1 ->
      		tmp = dynticks_nmi_nesting;
      		tmp = tmp - BUSY_INCBY;
      		dynticks_nmi_nesting = tmp;
      	:: else ->
      		dynticks_nmi_nesting = 0;
      		atomic {
      			dynticks = dynticks + 1;
      		}
      		assert((dynticks & 1) == 0);
      	fi;
      }
      
      /*
       * Base-level NMI runs non-atomically.  Crudely emulates process-level
       * dynticks-idle entry/exit.
       */
      proctype base_NMI()
      {
      	byte busy;
      
      	busy = 0;
      	do
      	::	/* Emulate base-level dynticks and not. */
      		if
      		:: 1 ->	atomic {
      				dynticks = dynticks + 1;
      			}
      			busy = 1;
      		:: 1 ->	skip;
      		fi;
      
      		/* Verify that we only sometimes have base-level dynticks. */
      		if
      		:: busy == 0 -> skip;
      		:: busy == 1 -> skip;
      		fi;
      
      		/* Model RCU's NMI entry and exit actions. */
      		rcu_nmi_enter();
      		assert((dynticks & 1) == 1);
      		rcu_nmi_exit();
      
      		/* Emulated re-entering base-level dynticks and not. */
      		if
      		:: !busy -> skip;
      		:: busy ->
      			atomic {
      				dynticks = dynticks + 1;
      			}
      			busy = 0;
      		fi;
      
      		/* We had better now be in dyntick-idle mode. */
      		assert((dynticks & 1) == 0);
      	od;
      }
      
      /*
       * Nested NMI runs atomically to emulate interrupting base_level().
       */
      proctype nested_NMI()
      {
      	do
      	::	/*
      		 * Use an atomic section to model a nested NMI.  This is
      		 * guaranteed to interleave into base_NMI() between a pair
      		 * of base_NMI() statements, just as a nested NMI would.
      		 */
      		atomic {
      			/* Verify that we only sometimes are in dynticks. */
      			if
      			:: (dynticks & 1) == 0 -> skip;
      			:: (dynticks & 1) == 1 -> skip;
      			fi;
      
      			/* Model RCU's NMI entry and exit actions. */
      			rcu_nmi_enter();
      			assert((dynticks & 1) == 1);
      			rcu_nmi_exit();
      		}
      	od;
      }
      
      init {
      	run base_NMI();
      	run nested_NMI();
      }
      
      ------------------------------------------------------------------------
      
      The following script can be used to run this model if placed in
      rcu_nmi.spin:
      
      ------------------------------------------------------------------------
      
      if ! spin -a rcu_nmi.spin
      then
      	echo Spin errors!!!
      	exit 1
      fi
      if ! cc -DSAFETY -o pan pan.c
      then
      	echo Compilation errors!!!
      	exit 1
      fi
      ./pan -m100000
      Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
      Reviewed-by: NLai Jiangshan <laijs@cn.fujitsu.com>
      734d1680
  3. 21 12月, 2014 8 次提交
    • L
      Linux 3.19-rc1 · 97bf6af1
      Linus Torvalds 提交于
      97bf6af1
    • L
      Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux · 60815cf2
      Linus Torvalds 提交于
      Pull ACCESS_ONCE cleanup preparation from Christian Borntraeger:
       "kernel: Provide READ_ONCE and ASSIGN_ONCE
      
        As discussed on LKML http://marc.info/?i=54611D86.4040306%40de.ibm.com
        ACCESS_ONCE might fail with specific compilers for non-scalar
        accesses.
      
        Here is a set of patches to tackle that problem.
      
        The first patch introduce READ_ONCE and ASSIGN_ONCE.  If the data
        structure is larger than the machine word size memcpy is used and a
        warning is emitted.  The next patches fix up several in-tree users of
        ACCESS_ONCE on non-scalar types.
      
        This does not yet contain a patch that forces ACCESS_ONCE to work only
        on scalar types.  This is targetted for the next merge window as Linux
        next already contains new offenders regarding ACCESS_ONCE vs.
        non-scalar types"
      
      * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux:
        s390/kvm: REPLACE barrier fixup with READ_ONCE
        arm/spinlock: Replace ACCESS_ONCE with READ_ONCE
        arm64/spinlock: Replace ACCESS_ONCE READ_ONCE
        mips/gup: Replace ACCESS_ONCE with READ_ONCE
        x86/gup: Replace ACCESS_ONCE with READ_ONCE
        x86/spinlock: Replace ACCESS_ONCE with READ_ONCE
        mm: replace ACCESS_ONCE with READ_ONCE or barriers
        kernel: Provide READ_ONCE and ASSIGN_ONCE
      60815cf2
    • L
      Merge tag 'clk-for-linus-3.19' of git://git.linaro.org/people/mike.turquette/linux · bfc7249c
      Linus Torvalds 提交于
      Pull clk framework updates from Mike Turquette:
       "This is much later than usual due to several last minute bugs that had
        to be addressed.  As usual the majority of changes are new drivers and
        modifications to existing drivers.  The core recieved many fixes along
        with the groundwork for several large changes coming in the future
        which will better parition clock providers from clock consumers"
      
      * tag 'clk-for-linus-3.19' of git://git.linaro.org/people/mike.turquette/linux: (86 commits)
        clk: samsung: Fix Exynos 5420 pinctrl setup and clock disable failure due to domain being gated
        ARM: OMAP3: clock: fix boot breakage in legacy mode
        ARM: OMAP2+: clock: fix DPLL code to use new determine rate APIs
        clk: Really fix deadlock with mmap_sem
        clk: mmp: fix sparse non static symbol warning
        clk: Change clk_ops->determine_rate to return a clk_hw as the best parent
        clk: change clk_debugfs_add_file to take a struct clk_hw
        clk: Don't expose __clk_get_accuracy
        clk: Don't try to use a struct clk* after it could have been freed
        clk: Remove unused function __clk_get_prepare_count
        clk: samsung: Fix double add of syscore ops after driver rebind
        clk: samsung: exynos4: set parent of sclk_hdmiphy to hdmi
        clk: samsung: exynos4415: Fix build with PM_SLEEP disabled
        clk: samsung: remove unnecessary inclusion of header files from clk.h
        clk: samsung: remove unnecessary CONFIG_OF from clk.c
        clk: samsung: Spelling s/bwtween/between/
        clk: rockchip: Add support for the mmc clock phases using the framework
        clk: rockchip: add bindings for the mmc clocks
        clk: rockchip: rk3288 export i2s0_clkout for use in DT
        clk: rockchip: use clock ID for DMC (memory controller) on rk3288
        ...
      bfc7249c
    • L
      Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux · a4e1328a
      Linus Torvalds 提交于
      Pull more i2c updates from Wolfram Sang:
       "Included are two bugfixes needing some bigger refactoring (sh_mobile:
        deferred probe with DMA, mv64xxx: fix offload support) and one
        deprecated driver removal I thought would go in via ppc but I
        misunderstood.  It has a proper ack from BenH"
      
      * 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
        i2c: sh_mobile: fix uninitialized var when debug is enabled
        macintosh: therm_pm72: delete deprecated driver
        i2c: sh_mobile: I2C_SH_MOBILE should depend on HAS_DMA
        i2c: sh_mobile: rework deferred probing
        i2c: sh_mobile: refactor DMA setup
        i2c: mv64xxx: rework offload support to fix several problems
        i2c: mv64xxx: use BIT() macro for register value definitions
      a4e1328a
    • L
      Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi · cdce6ac2
      Linus Torvalds 提交于
      Pull SCSI update from James Bottomley:
       "This is a much shorter set of patches that were on the go but didn't
        make it in to the early pull request for the merge window.  It's
        really a set of bug fixes plus some final cleanup work on the new tag
        queue API"
      
      * tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
        storvsc: ring buffer failures may result in I/O freeze
        ipr: set scsi_level correctly for disk arrays
        ipr: add support for async scanning to speed up boot
        scsi_debug: fix missing "break;" in SDEBUG_UA_CAPACITY_CHANGED case
        scsi_debug: take sdebug_host_list_lock when changing capacity
        scsi_debug: improve driver description in Kconfig
        scsi_debug: fix compare and write errors
        qla2xxx: fix race in handling rport deletion during recovery causes panic
        scsi: blacklist RSOC for Microsoft iSCSI target devices
        scsi: fix random memory corruption with scsi-mq + T10 PI
        Revert "[SCSI] mpt3sas: Remove phys on topology change"
        Revert "[SCSI] mpt2sas: Remove phys on topology change."
        esas2r: Correct typos of "validate" in a comment
        fc: FCP_PTA_SIMPLE is 0
        ibmvfc: remove unused tag variable
        scsi: remove MSG_*_TAG defines
        scsi: remove scsi_set_tag_type
        scsi: remove scsi_get_tag_type
        scsi: never drop to untagged mode during queue ramp down
        scsi: remove ->change_queue_type method
      cdce6ac2
    • L
      Merge tag 'pm-config-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm · 5d6a5468
      Linus Torvalds 提交于
      Pull CONFIG_PM_RUNTIME elimination from Rafael Wysocki:
       "This removes the last few uses of CONFIG_PM_RUNTIME introduced
        recently and makes that config option finally go away.
      
        CONFIG_PM will be available directly from the menu now and also it
        will be selected automatically if CONFIG_SUSPEND or CONFIG_HIBERNATION
        is set"
      
      * tag 'pm-config-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
        PM: Eliminate CONFIG_PM_RUNTIME
        tty: 8250_omap: Replace CONFIG_PM_RUNTIME with CONFIG_PM
        sound: sst-haswell-pcm: Replace CONFIG_PM_RUNTIME with CONFIG_PM
        spi: Replace CONFIG_PM_RUNTIME with CONFIG_PM
      5d6a5468
    • L
      Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild · 787140ad
      Linus Torvalds 提交于
      Pull misc kbuild changes from Michal Marek:
       "There are only a few things in the misc branch:
      
         - Fix for bugon.cocci semantic patch
         - Kdevelop4 files are .gitignored
         - Put make binrpm-pkg on diet"
      
      * 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild:
        scripts/package: binrpm-pkg do not create source and devel package
        .gitignore: Add Kdevelop4 project files
        bugon.cocci: fix Options at the macro
      787140ad
    • L
      Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild · d08372ca
      Linus Torvalds 提交于
      Pull kbuild updates from Michal Marek:
       "Here are the kbuild changes for v3.19-rc1:
      
         - Cleanups and deduplication in the main Makefile and
           scripts/Makefile.*
         - Sort the output of *config targets in make help
         - Old <linux/version.h> is always removed to avoid a surprise during
           bisecting
         - Warning fix in kconfig"
      
      * 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild:
        kbuild: remove redundant -rR flag of hdr-inst
        kbuild: Fix make help-<board series> on powerpc
        kbuild: Automatically remove stale <linux/version.h> file
        kconfig: Fix warning "‘jump’ may be used uninitialized"
        Makefile: sort list of defconfig targets in make help output
        kbuild: Remove duplicate $(cmd) definition in Makefile.clean
        kbuild: collect shorthands into scripts/Kbuild.include
      d08372ca
  4. 20 12月, 2014 23 次提交