1. 09 6月, 2020 8 次提交
    • K
      doc: cgroup: update note about conditions when oom killer is invoked · db33ec37
      Konstantin Khlebnikov 提交于
      Starting from v4.19 commit 29ef680a ("memcg, oom: move out_of_memory
      back to the charge path") cgroup oom killer is no longer invoked only
      from page faults.  Now it implements the same semantics as global OOM
      killer: allocation context invokes OOM killer and keeps retrying until
      success.
      
      [akpm@linux-foundation.org: fixes per Randy]
      Signed-off-by: NKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Roman Gushchin <guro@fb.com>
      Cc: Randy Dunlap <rdunlap@infradead.org>
      Link: http://lkml.kernel.org/r/158894738928.208854.5244393925922074518.stgit@buzzSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      db33ec37
    • G
      panic: add sysctl to dump all CPUs backtraces on oops event · 60c958d8
      Guilherme G. Piccoli 提交于
      Usually when the kernel reaches an oops condition, it's a point of no
      return; in case not enough debug information is available in the kernel
      splat, one of the last resorts would be to collect a kernel crash dump
      and analyze it.  The problem with this approach is that in order to
      collect the dump, a panic is required (to kexec-load the crash kernel).
      When in an environment of multiple virtual machines, users may prefer to
      try living with the oops, at least until being able to properly shutdown
      their VMs / finish their important tasks.
      
      This patch implements a way to collect a bit more debug details when an
      oops event is reached, by printing all the CPUs backtraces through the
      usage of NMIs (on architectures that support that).  The sysctl added
      (and documented) here was called "oops_all_cpu_backtrace", and when set
      will (as the name suggests) dump all CPUs backtraces.
      
      Far from ideal, this may be the last option though for users that for
      some reason cannot panic on oops.  Most of times oopses are clear enough
      to indicate the kernel portion that must be investigated, but in virtual
      environments it's possible to observe hypervisor/KVM issues that could
      lead to oopses shown in other guests CPUs (like virtual APIC crashes).
      This patch hence aims to help debug such complex issues without
      resorting to kdump.
      Signed-off-by: NGuilherme G. Piccoli <gpiccoli@canonical.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NKees Cook <keescook@chromium.org>
      Cc: Luis Chamberlain <mcgrof@kernel.org>
      Cc: Iurii Zaikin <yzaikin@google.com>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Vlastimil Babka <vbabka@suse.cz>
      Cc: Randy Dunlap <rdunlap@infradead.org>
      Cc: Matthew Wilcox <willy@infradead.org>
      Link: http://lkml.kernel.org/r/20200327224116.21030-1-gpiccoli@canonical.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      60c958d8
    • G
      kernel/hung_task.c: introduce sysctl to print all traces when a hung task is detected · 0ec9dc9b
      Guilherme G. Piccoli 提交于
      Commit 401c636a ("kernel/hung_task.c: show all hung tasks before
      panic") introduced a change in that we started to show all CPUs
      backtraces when a hung task is detected _and_ the sysctl/kernel
      parameter "hung_task_panic" is set.  The idea is good, because usually
      when observing deadlocks (that may lead to hung tasks), the culprit is
      another task holding a lock and not necessarily the task detected as
      hung.
      
      The problem with this approach is that dumping backtraces is a slightly
      expensive task, specially printing that on console (and specially in
      many CPU machines, as servers commonly found nowadays).  So, users that
      plan to collect a kdump to investigate the hung tasks and narrow down
      the deadlock definitely don't need the CPUs backtrace on dmesg/console,
      which will delay the panic and pollute the log (crash tool would easily
      grab all CPUs traces with 'bt -a' command).
      
      Also, there's the reciprocal scenario: some users may be interested in
      seeing the CPUs backtraces but not have the system panic when a hung
      task is detected.  The current approach hence is almost as embedding a
      policy in the kernel, by forcing the CPUs backtraces' dump (only) on
      hung_task_panic.
      
      This patch decouples the panic event on hung task from the CPUs
      backtraces dump, by creating (and documenting) a new sysctl called
      "hung_task_all_cpu_backtrace", analog to the approach taken on soft/hard
      lockups, that have both a panic and an "all_cpu_backtrace" sysctl to
      allow individual control.  The new mechanism for dumping the CPUs
      backtraces on hung task detection respects "hung_task_warnings" by not
      dumping the traces in case there's no warnings left.
      Signed-off-by: NGuilherme G. Piccoli <gpiccoli@canonical.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NKees Cook <keescook@chromium.org>
      Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
      Link: http://lkml.kernel.org/r/20200327223646.20779-1-gpiccoli@canonical.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      0ec9dc9b
    • G
      kernel/watchdog.c: convert {soft/hard}lockup boot parameters to sysctl aliases · f117955a
      Guilherme G. Piccoli 提交于
      After a recent change introduced by Vlastimil's series [0], kernel is
      able now to handle sysctl parameters on kernel command line; also, the
      series introduced a simple infrastructure to convert legacy boot
      parameters (that duplicate sysctls) into sysctl aliases.
      
      This patch converts the watchdog parameters softlockup_panic and
      {hard,soft}lockup_all_cpu_backtrace to use the new alias infrastructure.
      It fixes the documentation too, since the alias only accepts values 0 or
      1, not the full range of integers.
      
      We also took the opportunity here to improve the documentation of the
      previously converted hung_task_panic (see the patch series [0]) and put
      the alias table in alphabetical order.
      
      [0] http://lkml.kernel.org/r/20200427180433.7029-1-vbabka@suse.czSigned-off-by: NGuilherme G. Piccoli <gpiccoli@canonical.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Acked-by: NVlastimil Babka <vbabka@suse.cz>
      Cc: Kees Cook <keescook@chromium.org>
      Cc: Iurii Zaikin <yzaikin@google.com>
      Cc: Luis Chamberlain <mcgrof@kernel.org>
      Link: http://lkml.kernel.org/r/20200507214624.21911-1-gpiccoli@canonical.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      f117955a
    • V
      kernel/hung_task convert hung_task_panic boot parameter to sysctl · b467f3ef
      Vlastimil Babka 提交于
      We can now handle sysctl parameters on kernel command line and have
      infrastructure to convert legacy command line options that duplicate
      sysctl to become a sysctl alias.
      
      This patch converts the hung_task_panic parameter.  Note that the sysctl
      handler is more strict and allows only 0 and 1, while the legacy
      parameter allowed any non-zero value.  But there is little reason anyone
      would not be using 1.
      Signed-off-by: NVlastimil Babka <vbabka@suse.cz>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NKees Cook <keescook@chromium.org>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Alexey Dobriyan <adobriyan@gmail.com>
      Cc: Christian Brauner <christian.brauner@ubuntu.com>
      Cc: David Rientjes <rientjes@google.com>
      Cc: "Eric W . Biederman" <ebiederm@xmission.com>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: "Guilherme G . Piccoli" <gpiccoli@canonical.com>
      Cc: Iurii Zaikin <yzaikin@google.com>
      Cc: Ivan Teterevkov <ivan.teterevkov@nutanix.com>
      Cc: Luis Chamberlain <mcgrof@kernel.org>
      Cc: Masami Hiramatsu <mhiramat@kernel.org>
      Cc: Matthew Wilcox <willy@infradead.org>
      Cc: Michal Hocko <mhocko@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Link: http://lkml.kernel.org/r/20200427180433.7029-4-vbabka@suse.czSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      b467f3ef
    • V
      kernel/sysctl: support setting sysctl parameters from kernel command line · 3db978d4
      Vlastimil Babka 提交于
      Patch series "support setting sysctl parameters from kernel command line", v3.
      
      This series adds support for something that seems like many people
      always wanted but nobody added it yet, so here's the ability to set
      sysctl parameters via kernel command line options in the form of
      sysctl.vm.something=1
      
      The important part is Patch 1.  The second, not so important part is an
      attempt to clean up legacy one-off parameters that do the same thing as
      a sysctl.  I don't want to remove them completely for compatibility
      reasons, but with generic sysctl support the idea is to remove the
      one-off param handlers and treat the parameters as aliases for the
      sysctl variants.
      
      I have identified several parameters that mention sysctl counterparts in
      Documentation/admin-guide/kernel-parameters.txt but there might be more.
      The conversion also has varying level of success:
      
       - numa_zonelist_order is converted in Patch 2 together with adding the
         necessary infrastructure. It's easy as it doesn't really do anything
         but warn on deprecated value these days.
      
       - hung_task_panic is converted in Patch 3, but there's a downside that
         now it only accepts 0 and 1, while previously it was any integer
         value
      
       - nmi_watchdog maps to two sysctls nmi_watchdog and hardlockup_panic,
         so there's no straighforward conversion possible
      
       - traceoff_on_warning is a flag without value and it would be required
         to handle that somehow in the conversion infractructure, which seems
         pointless for a single flag
      
      This patch (of 5):
      
      A recently proposed patch to add vm_swappiness command line parameter in
      addition to existing sysctl [1] made me wonder why we don't have a
      general support for passing sysctl parameters via command line.
      
      Googling found only somebody else wondering the same [2], but I haven't
      found any prior discussion with reasons why not to do this.
      
      Settings the vm_swappiness issue aside (the underlying issue might be
      solved in a different way), quick search of kernel-parameters.txt shows
      there are already some that exist as both sysctl and kernel parameter -
      hung_task_panic, nmi_watchdog, numa_zonelist_order, traceoff_on_warning.
      
      A general mechanism would remove the need to add more of those one-offs
      and might be handy in situations where configuration by e.g.
      /etc/sysctl.d/ is impractical.
      
      Hence, this patch adds a new parse_args() pass that looks for parameters
      prefixed by 'sysctl.' and tries to interpret them as writes to the
      corresponding sys/ files using an temporary in-kernel procfs mount.
      This mechanism was suggested by Eric W.  Biederman [3], as it handles
      all dynamically registered sysctl tables, even though we don't handle
      modular sysctls.  Errors due to e.g.  invalid parameter name or value
      are reported in the kernel log.
      
      The processing is hooked right before the init process is loaded, as
      some handlers might be more complicated than simple setters and might
      need some subsystems to be initialized.  At the moment the init process
      can be started and eventually execute a process writing to /proc/sys/
      then it should be also fine to do that from the kernel.
      
      Sysctls registered later on module load time are not set by this
      mechanism - it's expected that in such scenarios, setting sysctl values
      from userspace is practical enough.
      
      [1] https://lore.kernel.org/r/BL0PR02MB560167492CA4094C91589930E9FC0@BL0PR02MB5601.namprd02.prod.outlook.com/
      [2] https://unix.stackexchange.com/questions/558802/how-to-set-sysctl-using-kernel-command-line-parameter
      [3] https://lore.kernel.org/r/87bloj2skm.fsf@x220.int.ebiederm.org/Signed-off-by: NVlastimil Babka <vbabka@suse.cz>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NLuis Chamberlain <mcgrof@kernel.org>
      Reviewed-by: NMasami Hiramatsu <mhiramat@kernel.org>
      Acked-by: NKees Cook <keescook@chromium.org>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Iurii Zaikin <yzaikin@google.com>
      Cc: Ivan Teterevkov <ivan.teterevkov@nutanix.com>
      Cc: Michal Hocko <mhocko@kernel.org>
      Cc: David Rientjes <rientjes@google.com>
      Cc: Matthew Wilcox <willy@infradead.org>
      Cc: "Eric W . Biederman" <ebiederm@xmission.com>
      Cc: "Guilherme G . Piccoli" <gpiccoli@canonical.com>
      Cc: Alexey Dobriyan <adobriyan@gmail.com>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: Christian Brauner <christian.brauner@ubuntu.com>
      Link: http://lkml.kernel.org/r/20200427180433.7029-1-vbabka@suse.cz
      Link: http://lkml.kernel.org/r/20200427180433.7029-2-vbabka@suse.czSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      3db978d4
    • R
      kernel: add panic_on_taint · db38d5c1
      Rafael Aquini 提交于
      Analogously to the introduction of panic_on_warn, this patch introduces
      a kernel option named panic_on_taint in order to provide a simple and
      generic way to stop execution and catch a coredump when the kernel gets
      tainted by any given flag.
      
      This is useful for debugging sessions as it avoids having to rebuild the
      kernel to explicitly add calls to panic() into the code sites that
      introduce the taint flags of interest.
      
      For instance, if one is interested in proceeding with a post-mortem
      analysis at the point a given code path is hitting a bad page (i.e.
      unaccount_page_cache_page(), or slab_bug()), a coredump can be collected
      by rebooting the kernel with 'panic_on_taint=0x20' amended to the
      command line.
      
      Another, perhaps less frequent, use for this option would be as a means
      for assuring a security policy case where only a subset of taints, or no
      single taint (in paranoid mode), is allowed for the running system.  The
      optional switch 'nousertaint' is handy in this particular scenario, as
      it will avoid userspace induced crashes by writes to sysctl interface
      /proc/sys/kernel/tainted causing false positive hits for such policies.
      
      [akpm@linux-foundation.org: tweak kernel-parameters.txt wording]
      Suggested-by: NQian Cai <cai@lca.pw>
      Signed-off-by: NRafael Aquini <aquini@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NLuis Chamberlain <mcgrof@kernel.org>
      Cc: Dave Young <dyoung@redhat.com>
      Cc: Baoquan He <bhe@redhat.com>
      Cc: Jonathan Corbet <corbet@lwn.net>
      Cc: Kees Cook <keescook@chromium.org>
      Cc: Randy Dunlap <rdunlap@infradead.org>
      Cc: "Theodore Ts'o" <tytso@mit.edu>
      Cc: Adrian Bunk <bunk@kernel.org>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: Laura Abbott <labbott@redhat.com>
      Cc: Jeff Mahoney <jeffm@suse.com>
      Cc: Jiri Kosina <jikos@kernel.org>
      Cc: Takashi Iwai <tiwai@suse.de>
      Link: http://lkml.kernel.org/r/20200515175502.146720-1-aquini@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      db38d5c1
    • O
      dynamic_debug: add an option to enable dynamic debug for modules only · ceabef7d
      Orson Zhai 提交于
      Instead of enabling dynamic debug globally with CONFIG_DYNAMIC_DEBUG,
      CONFIG_DYNAMIC_DEBUG_CORE will only enable core function of dynamic
      debug.  With the DYNAMIC_DEBUG_MODULE defined for any modules, dynamic
      debug will be tied to them.
      
      This is useful for people who only want to enable dynamic debug for
      kernel modules without worrying about kernel image size and memory
      consumption is increasing too much.
      
      [orson.zhai@unisoc.com: v2]
        Link: http://lkml.kernel.org/r/1587408228-10861-1-git-send-email-orson.unisoc@gmail.comSigned-off-by: NOrson Zhai <orson.zhai@unisoc.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Acked-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      Acked-by: NPetr Mladek <pmladek@suse.com>
      Cc: Jonathan Corbet <corbet@lwn.net>
      Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
      Cc: Steven Rostedt <rostedt@goodmis.org>
      Cc: Jason Baron <jbaron@akamai.com>
      Cc: Randy Dunlap <rdunlap@infradead.org>
      Link: http://lkml.kernel.org/r/1586521984-5890-1-git-send-email-orson.unisoc@gmail.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      ceabef7d
  2. 06 6月, 2020 1 次提交
  3. 04 6月, 2020 4 次提交
  4. 03 6月, 2020 2 次提交
    • J
      mm/memcg: automatically penalize tasks with high swap use · 4b82ab4f
      Jakub Kicinski 提交于
      Add a memory.swap.high knob, which can be used to protect the system
      from SWAP exhaustion.  The mechanism used for penalizing is similar to
      memory.high penalty (sleep on return to user space).
      
      That is not to say that the knob itself is equivalent to memory.high.
      The objective is more to protect the system from potentially buggy tasks
      consuming a lot of swap and impacting other tasks, or even bringing the
      whole system to stand still with complete SWAP exhaustion.  Hopefully
      without the need to find per-task hard limits.
      
      Slowing misbehaving tasks down gradually allows user space oom killers
      or other protection mechanisms to react.  oomd and earlyoom already do
      killing based on swap exhaustion, and memory.swap.high protection will
      help implement such userspace oom policies more reliably.
      
      We can use one counter for number of pages allocated under pressure to
      save struct task space and avoid two separate hierarchy walks on the hot
      path.  The exact overage is calculated on return to user space, anyway.
      
      Take the new high limit into account when determining if swap is "full".
      Borrowing the explanation from Johannes:
      
        The idea behind "swap full" is that as long as the workload has plenty
        of swap space available and it's not changing its memory contents, it
        makes sense to generously hold on to copies of data in the swap device,
        even after the swapin.  A later reclaim cycle can drop the page without
        any IO.  Trading disk space for IO.
      
        But the only two ways to reclaim a swap slot is when they're faulted
        in and the references go away, or by scanning the virtual address space
        like swapoff does - which is very expensive (one could argue it's too
        expensive even for swapoff, it's often more practical to just reboot).
      
        So at some point in the fill level, we have to start freeing up swap
        slots on fault/swapin.  Otherwise we could eventually run out of swap
        slots while they're filled with copies of data that is also in RAM.
      
        We don't want to OOM a workload because its available swap space is
        filled with redundant cache.
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Acked-by: NJohannes Weiner <hannes@cmpxchg.org>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Chris Down <chris@chrisdown.name>
      Cc: Shakeel Butt <shakeelb@google.com>
      Cc: Michal Hocko <mhocko@kernel.org>
      Cc: Hugh Dickins <hughd@google.com>
      Link: http://lkml.kernel.org/r/20200527195846.102707-5-kuba@kernel.orgSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      4b82ab4f
    • Y
      mm, memcg: add workingset_restore in memory.stat · a6f5576b
      Yafang Shao 提交于
      There's a new workingset counter introduced in commit 1899ad18 ("mm:
      workingset: tell cache transitions from workingset thrashing").  With
      the help of this counter we can know the workingset is transitioning or
      thrashing.  To leverage the benifit of this counter to memcg, we should
      introduce it into memory.stat.  Then we could know the workingset of the
      workload inside a memcg better.
      
      Bellow is the verification of this new counter in memory.stat.  Read a
      file into the memory and then read it again to make these pages be
      active.  The size of this file is 1G.  (memory.max is greater than file
      size) The counters in memory.stat will be
      
      	inactive_file 0
      	active_file 1073639424
      
      	workingset_refault 0
      	workingset_activate 0
      	workingset_restore 0
      	workingset_nodereclaim 0
      
      Trigger the memcg reclaim by setting a lower value to memory.high, and
      then some pages will be demoted into inactive list, and then some pages
      in the inactive list will be evicted into the storage.
      
      	inactive_file 498094080
      	active_file 310063104
      
      	workingset_refault 0
      	workingset_activate 0
      	workingset_restore 0
      	workingset_nodereclaim 0
      
      Then recover the memory.high and read the file into memory again.  As a
      result of it, the transitioning will occur.  Bellow is the result of
      this transitioning,
      
      	inactive_file 498094080
      	active_file 575397888
      
      	workingset_refault 64746
      	workingset_activate 64746
      	workingset_restore 64746
      	workingset_nodereclaim 0
      Signed-off-by: NYafang Shao <laoar.shao@gmail.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Acked-by: NJohannes Weiner <hannes@cmpxchg.org>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Acked-by: NChris Down <chris@chrisdown.name>
      Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
      Cc: Suren Baghdasaryan <surenb@google.com>
      Cc: Shakeel Butt <shakeelb@google.com>
      Link: http://lkml.kernel.org/r/20200504153522.11553-1-laoar.shao@gmail.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      a6f5576b
  5. 02 6月, 2020 1 次提交
  6. 01 6月, 2020 2 次提交
  7. 31 5月, 2020 2 次提交
  8. 28 5月, 2020 1 次提交
    • B
      cgroup: add cpu.stat file to root cgroup · 936f2a70
      Boris Burkov 提交于
      Currently, the root cgroup does not have a cpu.stat file. Add one which
      is consistent with /proc/stat to capture global cpu statistics that
      might not fall under cgroup accounting.
      
      We haven't done this in the past because the data are already presented
      in /proc/stat and we didn't want to add overhead from collecting root
      cgroup stats when cgroups are configured, but no cgroups have been
      created.
      
      By keeping the data consistent with /proc/stat, I think we avoid the
      first problem, while improving the usability of cgroups stats.
      We avoid the second problem by computing the contents of cpu.stat from
      existing data collected for /proc/stat anyway.
      Signed-off-by: NBoris Burkov <boris@bur.io>
      Suggested-by: NTejun Heo <tj@kernel.org>
      Signed-off-by: NTejun Heo <tj@kernel.org>
      936f2a70
  9. 26 5月, 2020 4 次提交
  10. 22 5月, 2020 1 次提交
  11. 21 5月, 2020 1 次提交
    • H
      dm zoned: metadata version 2 · bd5c4031
      Hannes Reinecke 提交于
      Implement handling for metadata version 2. The new metadata adds a
      label and UUID for the device mapper device, and additional UUID for
      the underlying block devices.
      
      It also allows for an additional regular drive to be used for
      emulating random access zones. The emulated zones will be placed
      logically in front of the zones from the zoned block device, causing
      the superblocks and metadata to be stored on that device.
      
      The first zone of the original zoned device will be used to hold
      another, tertiary copy of the metadata; this copy carries a generation
      number of 0 and is never updated; it's just used for identification.
      Signed-off-by: NHannes Reinecke <hare@suse.de>
      Reviewed-by: NBob Liu <bob.liu@oracle.com>
      Reviewed-by: NDamien Le Moal <damien.lemoal@wdc.com>
      Signed-off-by: NMike Snitzer <snitzer@redhat.com>
      bd5c4031
  12. 20 5月, 2020 2 次提交
  13. 19 5月, 2020 1 次提交
  14. 18 5月, 2020 2 次提交
  15. 17 5月, 2020 1 次提交
  16. 16 5月, 2020 5 次提交
  17. 15 5月, 2020 2 次提交