Linux – the difference between a patch which reverts a commit and a “reversed patch”

linux-kernelpatch

Before May 6th, 2013, the fs/eventpoll.c file in the Linux kernel had the following line #1605:

if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))

On May 6th, a commit changes this to (patch):

From 1c441e921201d523b5a6036aea22b0b426bf1af2 Mon Sep 17 00:00:00 2001
From: Colin Cross <ccross@android.com>
Date: Mon, 06 May 2013 23:50:16 +0000
Subject: epoll: use freezable blocking call

Avoid waking up every thread sleeping in an epoll_wait call during
suspend and resume by calling a freezable blocking call.  Previous
patches modified the freezer to avoid sending wakeups to threads
that are blocked in freezable blocking calls.

This call was selected to be converted to a freezable call because
it doesn't hold any locks or release any resources when interrupted
that might be needed by another freezing task or a kernel driver
during suspend, and is a common site where idle userspace tasks are
blocked.

Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
(limited to 'fs/eventpoll.c')

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index deecc72..0cff443 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -34,6 +34,7 @@
 #include <linux/mutex.h>
 #include <linux/anon_inodes.h>
 #include <linux/device.h>
+#include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/mman.h>
@@ -1602,7 +1603,8 @@ fetch_events:
            }

            spin_unlock_irqrestore(&ep->lock, flags);
-           if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
+           if (!freezable_schedule_hrtimeout_range(to, slack,
+                               HRTIMER_MODE_ABS))
                timed_out = 1;

            spin_lock_irqsave(&ep->lock, flags);
--
cgit v0.9.2

Then on October 29, 2013, after some issues with that, it is decided to revert "epoll: use freezable blocking call" – here's the patch:

From c511851de162e8ec03d62e7d7feecbdf590d881d Mon Sep 17 00:00:00 2001
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Date: Tue, 29 Oct 2013 12:12:56 +0000
Subject: Revert "epoll: use freezable blocking call"

This reverts commit 1c441e921201 (epoll: use freezable blocking call)
which is reported to cause user space memory corruption to happen
after suspend to RAM.

Since it appears to be extremely difficult to root cause this
problem, it is best to revert the offending commit and try to address
the original issue in a better way later.

References: https://bugzilla.kernel.org/show_bug.cgi?id=61781
Reported-by: Natrio <natrio@list.ru>
Reported-by: Jeff Pohlmeyer <yetanothergeek@gmail.com>
Bisected-by: Leo Wolf <jclw@ymail.com>
Fixes: 1c441e921201 (epoll: use freezable blocking call)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: 3.11+ <stable@vger.kernel.org> # 3.11+
---
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 473e09d..810c28f 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -34,7 +34,6 @@
 #include <linux/mutex.h>
 #include <linux/anon_inodes.h>
 #include <linux/device.h>
-#include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/mman.h>
@@ -1605,8 +1604,7 @@ fetch_events:
            }

            spin_unlock_irqrestore(&ep->lock, flags);
-           if (!freezable_schedule_hrtimeout_range(to, slack,
-                               HRTIMER_MODE_ABS))
+           if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
                timed_out = 1;

            spin_lock_irqsave(&ep->lock, flags);
--
cgit v0.9.2

The commit is accompanied by the following description:

This reverts commit 1c441e921201 (epoll: use freezable blocking call)
which is reported to cause user space memory corruption to happen
after suspend to RAM.

Since it appears to be extremely difficult to root cause this problem,
it is best to revert the offending commit and try to address the
original issue in a better way later.

Questions:

  1. Is this latest commit simply a patch that has the effect of
    reverting a prior patch OR is it a reversed patch?
  2. Assuming this was not a reversed patch, then what is a reversed patch? Supplying the exact same prior commit(May) and relying on the patch utility behavior for suggesting reversing the patch (see below, and "note for patch senders" at the bottom of the patch manpages)?
  3. Am I right in thinking that if I try to apply this latest patch to my kernel sources, and get the behavior shown below, that simply means the patch is already applied, and I can confirm this and indeed I have NO reference to freezable or the freeze include in my sources and that was the intent of the kernel maintainers here?
  4. I'm using Gentoo sources 3.10.25 and the changelog indicates:
    Linux patch 3.10.25 and the date is 21 Dec 2013? Except by looking
    at the changed .c file itself, how can I know if this patch has
    already been applied to my distribution sources? Can I rely on the
    version intro date in the sources changelog being 21st of Dec. and
    conclude that this patch has been applied because it was added to
    the kernel tree on October which is before?

Q3:

# patch -p1 < october29.patch
patching file fs/eventpoll.c
Reversed (or previously applied) patch detected!  Assume -R? [n]

Complement

A contributor explained:

A "reversed patch" is when someone accidentally makes a patch with
diff -u foo.c foo.c.orig (where foo.c is the newer file) instead of
the correct diff -u foo.c.orig foo.c

I was asking this because of what I found in the Note to patch senders in the patch manpages:

Take care not to send out reversed patches, since it makes people
wonder whether they already applied the patch.

This means that a reversed patch can be the result of a mistake like explained or a "technique" to roll back a change, but one that is not advisable because it creates confusion.

So indeed you can try diff -u new.c old.c (the mistake) here:

--- new.c   2014-02-01 21:37:55.616888434 -0500
+++ old.c   2014-02-01 21:37:41.430887944 -0500
@@ -34,6 +34,7 @@
 #include <linux/mutex.h>
 #include <linux/anon_inodes.h>
 #include <linux/device.h>
+#include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/mman.h>
@@ -1604,7 +1605,8 @@
            }

            spin_unlock_irqrestore(&ep->lock, flags);
-           if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
+           if (!freezable_schedule_hrtimeout_range(to, slack,
+                               HRTIMER_MODE_ABS))
                timed_out = 1;

            spin_lock_irqsave(&ep->lock, flags);

… and this is the original May 6th commit. So a reversed patch is in effect like submitting the original patch which would trigger the reversing behavior in the patch utility provided the patch is already applied, effectively rolling back to a state when the initial patch was not applied.

Ultimately, there can be no doubt that the patch has been applied to my sources. This is the latest eventpoll.c file in the git kernel tree. It contains no reference to 'freezable'. My sources neither. And trying to apply the patch triggers the previously applied patch message. In doubt look at the latest code in the tree (and git logs if you have a clone of the repository) and compare with what you have in your distribution sources.

Best Answer

It's a patch that undoes the earlier patch. It can be made with patch -R -pX bad.patch (where X is the number of directory levels to strip from the patch and bad.patch is the patch we want to undo) followed by a git commit

A "reversed patch" is when someone accidentally makes a patch with diff -u foo.c foo.c.orig (where foo.c is the newer file) instead of the correct diff -u foo.c.orig foo.c

The "reversed or previous applied patch" error indicates the patch has already been applied. I can not be more specific without knowing the contents of your kernelsuspend.patch file.

If you have the .git directory for the kernel source, you can look at the log for a single file with the git log command followed by the file name. e.g. git log fs/eventpoll.c or even git log -p fs/eventpoll.c.