From 9936a6f27279d137849bfa4a14ef9ed72780ce3e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 3 Oct 2014 12:18:32 -0700 Subject: [PATCH] 3.10-stable patches added patches: fs-notify-don-t-show-f_handle-if-exportfs_encode_inode_fh-failed.patch fsnotify-fdinfo-use-named-constants-instead-of-hardcoded-values.patch kcmp-fix-standard-comparison-bug.patch nilfs2-fix-data-loss-with-mmap.patch ocfs2-dlm-do-not-get-resource-spinlock-if-lockres-is-new.patch revert-mac80211-disable-uapsd-if-all-acs-are-under-acm.patch --- ...e-if-exportfs_encode_inode_fh-failed.patch | 34 +++++ ...onstants-instead-of-hardcoded-values.patch | 43 ++++++ .../kcmp-fix-standard-comparison-bug.patch | 137 ++++++++++++++++++ .../nilfs2-fix-data-loss-with-mmap.patch | 115 +++++++++++++++ ...-resource-spinlock-if-lockres-is-new.patch | 76 ++++++++++ ...sable-uapsd-if-all-acs-are-under-acm.patch | 38 +++++ queue-3.10/series | 6 + 7 files changed, 449 insertions(+) create mode 100644 queue-3.10/fs-notify-don-t-show-f_handle-if-exportfs_encode_inode_fh-failed.patch create mode 100644 queue-3.10/fsnotify-fdinfo-use-named-constants-instead-of-hardcoded-values.patch create mode 100644 queue-3.10/kcmp-fix-standard-comparison-bug.patch create mode 100644 queue-3.10/nilfs2-fix-data-loss-with-mmap.patch create mode 100644 queue-3.10/ocfs2-dlm-do-not-get-resource-spinlock-if-lockres-is-new.patch create mode 100644 queue-3.10/revert-mac80211-disable-uapsd-if-all-acs-are-under-acm.patch diff --git a/queue-3.10/fs-notify-don-t-show-f_handle-if-exportfs_encode_inode_fh-failed.patch b/queue-3.10/fs-notify-don-t-show-f_handle-if-exportfs_encode_inode_fh-failed.patch new file mode 100644 index 00000000000..bb146ecafd2 --- /dev/null +++ b/queue-3.10/fs-notify-don-t-show-f_handle-if-exportfs_encode_inode_fh-failed.patch @@ -0,0 +1,34 @@ +From 7e8824816bda16bb11ff5ff1e1212d642e57b0b3 Mon Sep 17 00:00:00 2001 +From: Andrey Vagin +Date: Tue, 9 Sep 2014 14:51:06 -0700 +Subject: fs/notify: don't show f_handle if exportfs_encode_inode_fh failed + +From: Andrey Vagin + +commit 7e8824816bda16bb11ff5ff1e1212d642e57b0b3 upstream. + +Currently we handle only ENOSPC. In case of other errors the file_handle +variable isn't filled properly and we will show a part of stack. + +Signed-off-by: Andrey Vagin +Acked-by: Cyrill Gorcunov +Cc: Alexander Viro +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/notify/fdinfo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/notify/fdinfo.c ++++ b/fs/notify/fdinfo.c +@@ -50,7 +50,7 @@ static int show_mark_fhandle(struct seq_ + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); +- if ((ret == FILEID_INVALID) || (ret == -ENOSPC)) { ++ if ((ret == FILEID_INVALID) || (ret < 0)) { + WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); + return 0; + } diff --git a/queue-3.10/fsnotify-fdinfo-use-named-constants-instead-of-hardcoded-values.patch b/queue-3.10/fsnotify-fdinfo-use-named-constants-instead-of-hardcoded-values.patch new file mode 100644 index 00000000000..e259f85f0ac --- /dev/null +++ b/queue-3.10/fsnotify-fdinfo-use-named-constants-instead-of-hardcoded-values.patch @@ -0,0 +1,43 @@ +From 1fc98d11cac6dd66342e5580cb2687e5b1e9a613 Mon Sep 17 00:00:00 2001 +From: Andrey Vagin +Date: Tue, 9 Sep 2014 14:51:04 -0700 +Subject: fsnotify/fdinfo: use named constants instead of hardcoded values + +From: Andrey Vagin + +commit 1fc98d11cac6dd66342e5580cb2687e5b1e9a613 upstream. + +MAX_HANDLE_SZ is equal to 128, but currently the size of pad is only 64 +bytes, so exportfs_encode_inode_fh can return an error. + +Signed-off-by: Andrey Vagin +Acked-by: Cyrill Gorcunov +Cc: Alexander Viro +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/notify/fdinfo.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/notify/fdinfo.c ++++ b/fs/notify/fdinfo.c +@@ -42,7 +42,7 @@ static int show_mark_fhandle(struct seq_ + { + struct { + struct file_handle handle; +- u8 pad[64]; ++ u8 pad[MAX_HANDLE_SZ]; + } f; + int size, ret, i; + +@@ -50,7 +50,7 @@ static int show_mark_fhandle(struct seq_ + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); +- if ((ret == 255) || (ret == -ENOSPC)) { ++ if ((ret == FILEID_INVALID) || (ret == -ENOSPC)) { + WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); + return 0; + } diff --git a/queue-3.10/kcmp-fix-standard-comparison-bug.patch b/queue-3.10/kcmp-fix-standard-comparison-bug.patch new file mode 100644 index 00000000000..7d2cf46ce28 --- /dev/null +++ b/queue-3.10/kcmp-fix-standard-comparison-bug.patch @@ -0,0 +1,137 @@ +From acbbe6fbb240a927ee1f5994f04d31267d422215 Mon Sep 17 00:00:00 2001 +From: Rasmus Villemoes +Date: Tue, 9 Sep 2014 14:51:01 -0700 +Subject: kcmp: fix standard comparison bug + +From: Rasmus Villemoes + +commit acbbe6fbb240a927ee1f5994f04d31267d422215 upstream. + +The C operator <= defines a perfectly fine total ordering on the set of +values representable in a long. However, unlike its namesake in the +integers, it is not translation invariant, meaning that we do not have +"b <= c" iff "a+b <= a+c" for all a,b,c. + +This means that it is always wrong to try to boil down the relationship +between two longs to a question about the sign of their difference, +because the resulting relation [a LEQ b iff a-b <= 0] is neither +anti-symmetric or transitive. The former is due to -LONG_MIN==LONG_MIN +(take any two a,b with a-b = LONG_MIN; then a LEQ b and b LEQ a, but a != +b). The latter can either be seen observing that x LEQ x+1 for all x, +implying x LEQ x+1 LEQ x+2 ... LEQ x-1 LEQ x; or more directly with the +simple example a=LONG_MIN, b=0, c=1, for which a-b < 0, b-c < 0, but a-c > +0. + +Note that it makes absolutely no difference that a transmogrying bijection +has been applied before the comparison is done. In fact, had the +obfuscation not been done, one could probably not observe the bug +(assuming all values being compared always lie in one half of the address +space, the mathematical value of a-b is always representable in a long). +As it stands, one can easily obtain three file descriptors exhibiting the +non-transitivity of kcmp(). + +Side note 1: I can't see that ensuring the MSB of the multiplier is +set serves any purpose other than obfuscating the obfuscating code. + +Side note 2: +#include +#include +#include +#include +#include +#include +#include + +enum kcmp_type { + KCMP_FILE, + KCMP_VM, + KCMP_FILES, + KCMP_FS, + KCMP_SIGHAND, + KCMP_IO, + KCMP_SYSVSEM, + KCMP_TYPES, +}; +pid_t pid; + +int kcmp(pid_t pid1, pid_t pid2, int type, + unsigned long idx1, unsigned long idx2) +{ + return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2); +} +int cmp_fd(int fd1, int fd2) +{ + int c = kcmp(pid, pid, KCMP_FILE, fd1, fd2); + if (c < 0) { + perror("kcmp"); + exit(1); + } + assert(0 <= c && c < 3); + return c; +} +int cmp_fdp(const void *a, const void *b) +{ + static const int normalize[] = {0, -1, 1}; + return normalize[cmp_fd(*(int*)a, *(int*)b)]; +} +#define MAX 100 /* This is plenty; I've seen it trigger for MAX==3 */ +int main(int argc, char *argv[]) +{ + int r, s, count = 0; + int REL[3] = {0,0,0}; + int fd[MAX]; + pid = getpid(); + while (count < MAX) { + r = open("/dev/null", O_RDONLY); + if (r < 0) + break; + fd[count++] = r; + } + printf("opened %d file descriptors\n", count); + for (r = 0; r < count; ++r) { + for (s = r+1; s < count; ++s) { + REL[cmp_fd(fd[r], fd[s])]++; + } + } + printf("== %d\t< %d\t> %d\n", REL[0], REL[1], REL[2]); + qsort(fd, count, sizeof(fd[0]), cmp_fdp); + memset(REL, 0, sizeof(REL)); + + for (r = 0; r < count; ++r) { + for (s = r+1; s < count; ++s) { + REL[cmp_fd(fd[r], fd[s])]++; + } + } + printf("== %d\t< %d\t> %d\n", REL[0], REL[1], REL[2]); + return (REL[0] + REL[2] != 0); +} + +Signed-off-by: Rasmus Villemoes +Reviewed-by: Cyrill Gorcunov +"Eric W. Biederman" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/kcmp.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/kernel/kcmp.c ++++ b/kernel/kcmp.c +@@ -44,11 +44,12 @@ static long kptr_obfuscate(long v, int t + */ + static int kcmp_ptr(void *v1, void *v2, enum kcmp_type type) + { +- long ret; ++ long t1, t2; + +- ret = kptr_obfuscate((long)v1, type) - kptr_obfuscate((long)v2, type); ++ t1 = kptr_obfuscate((long)v1, type); ++ t2 = kptr_obfuscate((long)v2, type); + +- return (ret < 0) | ((ret > 0) << 1); ++ return (t1 < t2) | ((t1 > t2) << 1); + } + + /* The caller must have pinned the task */ diff --git a/queue-3.10/nilfs2-fix-data-loss-with-mmap.patch b/queue-3.10/nilfs2-fix-data-loss-with-mmap.patch new file mode 100644 index 00000000000..43ecd83790a --- /dev/null +++ b/queue-3.10/nilfs2-fix-data-loss-with-mmap.patch @@ -0,0 +1,115 @@ +From 56d7acc792c0d98f38f22058671ee715ff197023 Mon Sep 17 00:00:00 2001 +From: Andreas Rohner +Date: Thu, 25 Sep 2014 16:05:14 -0700 +Subject: nilfs2: fix data loss with mmap() + +From: Andreas Rohner + +commit 56d7acc792c0d98f38f22058671ee715ff197023 upstream. + +This bug leads to reproducible silent data loss, despite the use of +msync(), sync() and a clean unmount of the file system. It is easily +reproducible with the following script: + + ----------------[BEGIN SCRIPT]-------------------- + mkfs.nilfs2 -f /dev/sdb + mount /dev/sdb /mnt + + dd if=/dev/zero bs=1M count=30 of=/mnt/testfile + + umount /mnt + mount /dev/sdb /mnt + CHECKSUM_BEFORE="$(md5sum /mnt/testfile)" + + /root/mmaptest/mmaptest /mnt/testfile 30 10 5 + + sync + CHECKSUM_AFTER="$(md5sum /mnt/testfile)" + umount /mnt + mount /dev/sdb /mnt + CHECKSUM_AFTER_REMOUNT="$(md5sum /mnt/testfile)" + umount /mnt + + echo "BEFORE MMAP:\t$CHECKSUM_BEFORE" + echo "AFTER MMAP:\t$CHECKSUM_AFTER" + echo "AFTER REMOUNT:\t$CHECKSUM_AFTER_REMOUNT" + ----------------[END SCRIPT]-------------------- + +The mmaptest tool looks something like this (very simplified, with +error checking removed): + + ----------------[BEGIN mmaptest]-------------------- + data = mmap(NULL, file_size - file_offset, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, file_offset); + + for (i = 0; i < write_count; ++i) { + memcpy(data + i * 4096, buf, sizeof(buf)); + msync(data, file_size - file_offset, MS_SYNC)) + } + ----------------[END mmaptest]-------------------- + +The output of the script looks something like this: + + BEFORE MMAP: 281ed1d5ae50e8419f9b978aab16de83 /mnt/testfile + AFTER MMAP: 6604a1c31f10780331a6850371b3a313 /mnt/testfile + AFTER REMOUNT: 281ed1d5ae50e8419f9b978aab16de83 /mnt/testfile + +So it is clear, that the changes done using mmap() do not survive a +remount. This can be reproduced a 100% of the time. The problem was +introduced in commit 136e8770cd5d ("nilfs2: fix issue of +nilfs_set_page_dirty() for page at EOF boundary"). + +If the page was read with mpage_readpage() or mpage_readpages() for +example, then it has no buffers attached to it. In that case +page_has_buffers(page) in nilfs_set_page_dirty() will be false. +Therefore nilfs_set_file_dirty() is never called and the pages are never +collected and never written to disk. + +This patch fixes the problem by also calling nilfs_set_file_dirty() if the +page has no buffers attached to it. + +[akpm@linux-foundation.org: s/PAGE_SHIFT/PAGE_CACHE_SHIFT/] +Signed-off-by: Andreas Rohner +Tested-by: Andreas Rohner +Signed-off-by: Ryusuke Konishi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nilfs2/inode.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include "nilfs.h" +@@ -219,10 +220,10 @@ static int nilfs_writepage(struct page * + + static int nilfs_set_page_dirty(struct page *page) + { ++ struct inode *inode = page->mapping->host; + int ret = __set_page_dirty_nobuffers(page); + + if (page_has_buffers(page)) { +- struct inode *inode = page->mapping->host; + unsigned nr_dirty = 0; + struct buffer_head *bh, *head; + +@@ -245,6 +246,10 @@ static int nilfs_set_page_dirty(struct p + + if (nr_dirty) + nilfs_set_file_dirty(inode, nr_dirty); ++ } else if (ret) { ++ unsigned nr_dirty = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); ++ ++ nilfs_set_file_dirty(inode, nr_dirty); + } + return ret; + } diff --git a/queue-3.10/ocfs2-dlm-do-not-get-resource-spinlock-if-lockres-is-new.patch b/queue-3.10/ocfs2-dlm-do-not-get-resource-spinlock-if-lockres-is-new.patch new file mode 100644 index 00000000000..334cc4823bc --- /dev/null +++ b/queue-3.10/ocfs2-dlm-do-not-get-resource-spinlock-if-lockres-is-new.patch @@ -0,0 +1,76 @@ +From 5760a97c7143c208fa3a8f8cad0ed7dd672ebd28 Mon Sep 17 00:00:00 2001 +From: Joseph Qi +Date: Thu, 25 Sep 2014 16:05:16 -0700 +Subject: ocfs2/dlm: do not get resource spinlock if lockres is new + +From: Joseph Qi + +commit 5760a97c7143c208fa3a8f8cad0ed7dd672ebd28 upstream. + +There is a deadlock case which reported by Guozhonghua: + https://oss.oracle.com/pipermail/ocfs2-devel/2014-September/010079.html + +This case is caused by &res->spinlock and &dlm->master_lock +misordering in different threads. + +It was introduced by commit 8d400b81cc83 ("ocfs2/dlm: Clean up refmap +helpers"). Since lockres is new, it doesn't not require the +&res->spinlock. So remove it. + +Fixes: 8d400b81cc83 ("ocfs2/dlm: Clean up refmap helpers") +Signed-off-by: Joseph Qi +Reviewed-by: joyce.xue +Reported-by: Guozhonghua +Cc: Joel Becker +Cc: Mark Fasheh +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/dlm/dlmmaster.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/fs/ocfs2/dlm/dlmmaster.c ++++ b/fs/ocfs2/dlm/dlmmaster.c +@@ -653,12 +653,9 @@ void dlm_lockres_clear_refmap_bit(struct + clear_bit(bit, res->refmap); + } + +- +-void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, ++static void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) + { +- assert_spin_locked(&res->spinlock); +- + res->inflight_locks++; + + mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name, +@@ -666,6 +663,13 @@ void dlm_lockres_grab_inflight_ref(struc + __builtin_return_address(0)); + } + ++void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, ++ struct dlm_lock_resource *res) ++{ ++ assert_spin_locked(&res->spinlock); ++ __dlm_lockres_grab_inflight_ref(dlm, res); ++} ++ + void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) + { +@@ -855,10 +859,8 @@ lookup: + /* finally add the lockres to its hash bucket */ + __dlm_insert_lockres(dlm, res); + +- /* Grab inflight ref to pin the resource */ +- spin_lock(&res->spinlock); +- dlm_lockres_grab_inflight_ref(dlm, res); +- spin_unlock(&res->spinlock); ++ /* since this lockres is new it doesn't not require the spinlock */ ++ __dlm_lockres_grab_inflight_ref(dlm, res); + + /* get an extra ref on the mle in case this is a BLOCK + * if so, the creator of the BLOCK may try to put the last diff --git a/queue-3.10/revert-mac80211-disable-uapsd-if-all-acs-are-under-acm.patch b/queue-3.10/revert-mac80211-disable-uapsd-if-all-acs-are-under-acm.patch new file mode 100644 index 00000000000..5d9a3c7f8fb --- /dev/null +++ b/queue-3.10/revert-mac80211-disable-uapsd-if-all-acs-are-under-acm.patch @@ -0,0 +1,38 @@ +From bb512ad0732232f1d2693bb68f31a76bed8f22ae Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 25 Aug 2014 12:08:09 +0200 +Subject: Revert "mac80211: disable uAPSD if all ACs are under ACM" + +From: Johannes Berg + +commit bb512ad0732232f1d2693bb68f31a76bed8f22ae upstream. + +This reverts commit 24aa11ab8ae03292d38ec0dbd9bc2ac49fe8a6dd. + +That commit was wrong since it uses data that hasn't even been set +up yet, but might be a hold-over from a previous connection. + +Additionally, it seems like a driver-specific workaround that +shouldn't have been in mac80211 to start with. + +Fixes: 24aa11ab8ae0 ("mac80211: disable uAPSD if all ACs are under ACM") +Reviewed-by: Luciano Coelho +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/mlme.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4395,8 +4395,7 @@ int ieee80211_mgd_assoc(struct ieee80211 + rcu_read_unlock(); + + if (bss->wmm_used && bss->uapsd_supported && +- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && +- sdata->wmm_acm != 0xff) { ++ (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { + assoc_data->uapsd = true; + ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; + } else { diff --git a/queue-3.10/series b/queue-3.10/series index 379d39edddb..b31da6f89d5 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -109,3 +109,9 @@ genhd-fix-leftover-might_sleep-in-blk_free_devt.patch usb-host-xhci-fix-compliance-mode-workaround.patch usb-dwc3-core-fix-order-of-pm-runtime-calls.patch usb-dwc3-core-fix-ordering-for-phy-suspend.patch +revert-mac80211-disable-uapsd-if-all-acs-are-under-acm.patch +kcmp-fix-standard-comparison-bug.patch +fsnotify-fdinfo-use-named-constants-instead-of-hardcoded-values.patch +fs-notify-don-t-show-f_handle-if-exportfs_encode_inode_fh-failed.patch +nilfs2-fix-data-loss-with-mmap.patch +ocfs2-dlm-do-not-get-resource-spinlock-if-lockres-is-new.patch -- 2.47.3