commit kernel-source for openSUSE:Factory
Hello community, here is the log from the commit of package kernel-source for openSUSE:Factory checked in at 2015-09-02 00:34:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kernel-source (Old) and /work/SRC/openSUSE:Factory/.kernel-source.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "kernel-source" Changes: -------- --- /work/SRC/openSUSE:Factory/kernel-source/kernel-debug.changes 2015-08-26 10:00:51.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.kernel-source.new/kernel-debug.changes 2015-09-02 00:35:00.000000000 +0200 @@ -1,0 +2,31 @@ +Fri Aug 28 12:59:34 CEST 2015 - jslaby@suse.cz + +- Refresh + patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch. + Hmm, mmc_data does not have sg_count yet. Fix it. +- commit d867e86 + +------------------------------------------------------------------- +Fri Aug 28 11:28:58 CEST 2015 - jslaby@suse.cz + +- Refresh + patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch. + Forgot to refresh :/. +- commit 9b2d57c + +------------------------------------------------------------------- +Fri Aug 28 11:13:33 CEST 2015 - jslaby@suse.cz + +- mmc: sdhci: fix dma memory leak in sdhci_pre_req() (bnc#934531). +- commit 3cca62a + +------------------------------------------------------------------- +Mon Aug 24 18:19:43 CEST 2015 - jeffm@suse.com + +- Btrfs: fix stale dir entries after unlink, inode eviction and + fsync (bsc#942925). +- Btrfs: fix stale directory entries after fsync log replay + (bsc#942925). +- commit 42e403f + +------------------------------------------------------------------- kernel-default.changes: same change kernel-desktop.changes: same change kernel-docs.changes: same change kernel-ec2.changes: same change kernel-lpae.changes: same change kernel-obs-build.changes: same change kernel-obs-qa-xen.changes: same change kernel-obs-qa.changes: same change kernel-pae.changes: same change kernel-pv.changes: same change kernel-source.changes: same change kernel-syms.changes: same change kernel-vanilla.changes: same change kernel-xen.changes: same change ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kernel-debug.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -61,7 +61,7 @@ Group: System/Kernel Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif kernel-default.spec: same change kernel-desktop.spec: same change ++++++ kernel-docs.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -29,7 +29,7 @@ Group: Documentation/Man Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif ++++++ kernel-ec2.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -61,7 +61,7 @@ Group: System/Kernel Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif kernel-lpae.spec: same change ++++++ kernel-obs-build.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -47,7 +47,7 @@ Group: SLES Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif kernel-obs-qa-xen.spec: same change kernel-obs-qa.spec: same change ++++++ kernel-pae.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -61,7 +61,7 @@ Group: System/Kernel Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif kernel-pv.spec: same change ++++++ kernel-source.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -32,7 +32,7 @@ Group: Development/Sources Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif ++++++ kernel-syms.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -27,7 +27,7 @@ Version: 4.1.6 %if %using_buildservice %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif ++++++ kernel-vanilla.spec ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:10.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:10.000000000 +0200 @@ -61,7 +61,7 @@ Group: System/Kernel Version: 4.1.6 %if 0%{?is_kotd} -Release: <RELEASE>.gce0123d +Release: <RELEASE>.gd867e86 %else Release: 0 %endif kernel-xen.spec: same change ++++++ patches.fixes.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/patches.fixes/btrfs-fix-stale-dir-entries-after-unlink-inode-eviction-and-fsync new/patches.fixes/btrfs-fix-stale-dir-entries-after-unlink-inode-eviction-and-fsync --- old/patches.fixes/btrfs-fix-stale-dir-entries-after-unlink-inode-eviction-and-fsync 1970-01-01 01:00:00.000000000 +0100 +++ new/patches.fixes/btrfs-fix-stale-dir-entries-after-unlink-inode-eviction-and-fsync 2015-08-28 12:59:34.000000000 +0200 @@ -0,0 +1,172 @@ +From: Filipe Manana <fdmanana@suse.com> +Date: Fri, 24 Jul 2015 06:30:42 +0100 +Subject: Btrfs: fix stale dir entries after unlink, inode eviction and fsync +Patch-mainline: Submitted, http://www.spinics.net/lists/linux-btrfs/msg45634.html +References: bsc#942925 + +If we remove a hard link from an inode, the inode gets evicted, then +we fsync the inode and then power fail/crash, when the log tree is +replayed, the parent directory inode still has entries pointing to +the name that no longer exists, while our inode no longer has the +BTRFS_INODE_REF_KEY item matching the deleted hard link (as expected), +leaving the filesystem in an inconsistent state. The stale directory +entries can not be deleted (an attempt to delete them causes -ESTALE +errors), which makes it impossible to delete the parent directory. + +This happens because we track the id of the transaction where the last +unlink operation for the inode happened (last_unlink_trans) in an +in-memory only field of the inode, that is, a value that is never +persisted in the inode item stored on the fs/subvol btree. So if an +inode is evicted and loaded again, the value for last_unlink_trans is +set to 0, which prevents the fsync from logging the parent directory +at btrfs_log_inode_parent(). So fix this by setting last_unlink_trans +to the id of the transaction that last modified the inode when we +load the inode. This is a pessimistic approach but it always ensures +correctness with the trade off of ocassional full transaction commits +when an fsync is done against the inode in the same transaction where +it was evicted and reloaded. + +The following test case for fstests triggers the problem: + + seq=`basename $0` + seqres=$RESULT_DIR/$seq + echo "QA output created by $seq" + tmp=/tmp/$$ + status=1 # failure is the default! + trap "_cleanup; exit \$status" 0 1 2 3 15 + + _cleanup() + { + _cleanup_flakey + rm -f $tmp.* + } + + # get standard environment, filters and checks + . ./common/rc + . ./common/filter + . ./common/dmflakey + + # real QA test starts here + _need_to_be_root + _supported_fs generic + _supported_os Linux + _require_scratch + _require_dm_flakey + _require_metadata_journaling $SCRATCH_DEV + + rm -f $seqres.full + + _scratch_mkfs >>$seqres.full 2>&1 + _init_flakey + _mount_flakey + + # Create our test file with 2 hard links. + mkdir $SCRATCH_MNT/testdir + touch $SCRATCH_MNT/testdir/foo + ln $SCRATCH_MNT/testdir/foo $SCRATCH_MNT/testdir/bar + + # Make sure everything done so far is durably persisted. + sync + + # Now remove one of the links, trigger inode eviction and then fsync + # our inode. + unlink $SCRATCH_MNT/testdir/bar + echo 2 > /proc/sys/vm/drop_caches + $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/testdir/foo + + # Silently drop all writes on our scratch device to simulate a power failure. + _load_flakey_table $FLAKEY_DROP_WRITES + _unmount_flakey + + # Allow writes again and mount the fs to trigger log/journal replay. + _load_flakey_table $FLAKEY_ALLOW_WRITES + _mount_flakey + + # Now verify our directory entries. + echo "Entries in testdir:" + ls -1 $SCRATCH_MNT/testdir + + # If we remove our inode, its parent should become empty and therefore we should + # be able to remove the parent. + rm -f $SCRATCH_MNT/testdir/* + rmdir $SCRATCH_MNT/testdir + + _unmount_flakey + + # The fstests framework will call fsck against our filesystem which will verify + # that all metadata is in a consistent state. + + status=0 + exit + +The test failed on btrfs with: + + generic/098 4s ... - output mismatch (see /home/fdmanana/git/hub/xfstests/results//generic/098.out.bad) +# --- tests/generic/098.out 2015-07-23 18:01:12.616175932 +0100 +# +++ /home/fdmanana/git/hub/xfstests/results//generic/098.out.bad 2015-07-23 18:04:58.924138308 +0100 + @@ -1,3 +1,6 @@ + QA output created by 098 + Entries in testdir: + +bar + foo + +rm: cannot remove '/home/fdmanana/btrfs-tests/scratch_1/testdir/foo': Stale file handle + +rmdir: failed to remove '/home/fdmanana/btrfs-tests/scratch_1/testdir': Directory not empty + ... + (Run 'diff -u tests/generic/098.out /home/fdmanana/git/hub/xfstests/results//generic/098.out.bad' to see the entire diff) + _check_btrfs_filesystem: filesystem on /dev/sdc is inconsistent (see /home/fdmanana/git/hub/xfstests/results//generic/098.full) + + $ cat /home/fdmanana/git/hub/xfstests/results//generic/098.full + (...) + checking fs roots + root 5 inode 258 errors 2001, no inode item, link count wrong + unresolved ref dir 257 index 0 namelen 3 name foo filetype 1 errors 6, no dir index, no inode ref + unresolved ref dir 257 index 3 namelen 3 name bar filetype 1 errors 5, no dir item, no inode ref + Checking filesystem on /dev/sdc + (...) + +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Acked-by: Jeff Mahoney <jeffm@suse.com> +--- + fs/btrfs/inode.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index cf7dc05..6847f93 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3654,6 +3654,34 @@ cache_index: + set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, + &BTRFS_I(inode)->runtime_flags); + ++ /* ++ * We don't persist the id of the transaction where an unlink operation ++ * against the inode was last made. So here we assume the inode might ++ * have been evicted, and therefore the exact value of last_unlink_trans ++ * lost, and set it to last_trans to avoid metadata inconsistencies ++ * between the inode and its if the inode is fsync'ed and the log ++ * replayed. For example, in the scenario: ++ * ++ * touch mydir/foo ++ * ln mydir/foo mydir/bar ++ * sync ++ * unlink mydir/bar ++ * echo 2 > /proc/sys/vm/drop_caches # evicts inode ++ * xfs_io -c fsync mydir/foo ++ * <power failure> ++ * mount fs, triggers fsync log replay ++ * ++ * We must make sure that when we fsync our inode foo we also log its ++ * parent inode, otherwise after log replay the parent still has the ++ * dentry with the "bar" name but our inode foo has a link count of 1 ++ * and doesn't have an inode ref with the name "bar" anymore. ++ * ++ * Setting last_unlink_trans to last_trans is a pessimistic approach, ++ * but it guarantees correctness at the expense of ocassional full ++ * transaction commits on fsync. ++ */ ++ BTRFS_I(inode)->last_unlink_trans = BTRFS_I(inode)->last_trans; ++ + path->slots[0]++; + if (inode->i_nlink != 1 || + path->slots[0] >= btrfs_header_nritems(leaf)) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/patches.fixes/btrfs-fix-stale-directory-entries-after-fsync-log-replay new/patches.fixes/btrfs-fix-stale-directory-entries-after-fsync-log-replay --- old/patches.fixes/btrfs-fix-stale-directory-entries-after-fsync-log-replay 1970-01-01 01:00:00.000000000 +0100 +++ new/patches.fixes/btrfs-fix-stale-directory-entries-after-fsync-log-replay 2015-08-28 12:59:34.000000000 +0200 @@ -0,0 +1,244 @@ +From: Filipe Manana <fdmanana@suse.com> +Date: Wed, 22 Jul 2015 04:54:54 +0100 +Subject: Btrfs: fix stale directory entries after fsync log replay +Patch-mainline: Submitted, http://www.spinics.net/lists/linux-btrfs/msg45480.html +References: bsc#942925 + +We have another case where after an fsync log replay we get an inode with +a wrong link count (smaller than it should be) and a number of directory +entries greater than its link count. This happens when we add a new link +hard link to our inode A and then we fsync some other inode B that has +the side effect of logging the parent directory inode too. In this case +at log replay time we add the new hard link to our inode (the item with +key BTRFS_INODE_REF_KEY) when processing the parent directory but we +never adjust the link count of our inode A. As a result we get stale dir +entries for our inode A that can never be deleted and therefore it makes +it impossible to remove the parent directory (as its i_size can never +decrease back to 0). + +A simple reproducer for fstests that triggers this issue: + + seq=`basename $0` + seqres=$RESULT_DIR/$seq + echo "QA output created by $seq" + tmp=/tmp/$$ + status=1 # failure is the default! + trap "_cleanup; exit \$status" 0 1 2 3 15 + + _cleanup() + { + _cleanup_flakey + rm -f $tmp.* + } + + # get standard environment, filters and checks + . ./common/rc + . ./common/filter + . ./common/dmflakey + + # real QA test starts here + _need_to_be_root + _supported_fs generic + _supported_os Linux + _require_scratch + _require_dm_flakey + _require_metadata_journaling $SCRATCH_DEV + + rm -f $seqres.full + + _scratch_mkfs >>$seqres.full 2>&1 + _init_flakey + _mount_flakey + + # Create our test directory and files. + mkdir $SCRATCH_MNT/testdir + touch $SCRATCH_MNT/testdir/foo + touch $SCRATCH_MNT/testdir/bar + + # Make sure everything done so far is durably persisted. + sync + + # Create one hard link for file foo and another one for file bar. After + # that fsync only the file bar. + ln $SCRATCH_MNT/testdir/bar $SCRATCH_MNT/testdir/bar_link + ln $SCRATCH_MNT/testdir/foo $SCRATCH_MNT/testdir/foo_link + $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/testdir/bar + + # Silently drop all writes on scratch device to simulate power failure. + _load_flakey_table $FLAKEY_DROP_WRITES + _unmount_flakey + + # Allow writes again and mount the fs to trigger log/journal replay. + _load_flakey_table $FLAKEY_ALLOW_WRITES + _mount_flakey + + # Now verify both our files have a link count of 2. + echo "Link count for file foo: $(stat --format=%h $SCRATCH_MNT/testdir/foo)" + echo "Link count for file bar: $(stat --format=%h $SCRATCH_MNT/testdir/bar)" + + # We should be able to remove all the links of our files in testdir, and + # after that the parent directory should become empty and therefore + # possible to remove it. + rm -f $SCRATCH_MNT/testdir/* + rmdir $SCRATCH_MNT/testdir + + _unmount_flakey + + # The fstests framework will call fsck against our filesystem which will verify + # that all metadata is in a consistent state. + + status=0 + exit + +The test fails with: + + -Link count for file foo: 2 + +Link count for file foo: 1 + Link count for file bar: 2 + +rm: cannot remove '/home/fdmanana/btrfs-tests/scratch_1/testdir/foo_link': Stale file handle + +rmdir: failed to remove '/home/fdmanana/btrfs-tests/scratch_1/testdir': Directory not empty + (...) + _check_btrfs_filesystem: filesystem on /dev/sdc is inconsistent + +And fsck's output: + + (...) + checking fs roots + root 5 inode 258 errors 2001, no inode item, link count wrong + unresolved ref dir 257 index 5 namelen 8 name foo_link filetype 1 errors 4, no inode ref + Checking filesystem on /dev/sdc + (...) + +So fix this by marking inodes for link count fixup at log replay time +whenever a directory entry is replayed if the entry was created in the +transaction where the fsync was made and if it points to a non-directory +inode. + +This isn't a new problem/regression, the issue exists for a long time, +possibly since the log tree feature was added (2008). + +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Acked-by: Jeff Mahoney <jeffm@suse.com> +--- + fs/btrfs/tree-log.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 60 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 9c45431..cb5666e 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1613,6 +1613,9 @@ static bool name_in_log_ref(struct btrfs_root *log_root, + * not exist in the FS, it is skipped. fsyncs on directories + * do not force down inodes inside that directory, just changes to the + * names or unlinks in a directory. ++ * ++ * Returns < 0 on error, 0 if the name wasn't replayed (dentry points to a ++ * non-existing inode) and 1 if the name was replayed. + */ + static noinline int replay_one_name(struct btrfs_trans_handle *trans, + struct btrfs_root *root, +@@ -1631,6 +1634,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, + int exists; + int ret = 0; + bool update_size = (key->type == BTRFS_DIR_INDEX_KEY); ++ bool name_added = false; + + dir = read_one_inode(root, key->objectid); + if (!dir) +@@ -1708,6 +1712,8 @@ out: + } + kfree(name); + iput(dir); ++ if (!ret && name_added) ++ ret = 1; + return ret; + + insert: +@@ -1723,6 +1729,8 @@ insert: + name, name_len, log_type, &log_key); + if (ret && ret != -ENOENT && ret != -EEXIST) + goto out; ++ if (!ret) ++ name_added = true; + update_size = false; + ret = 0; + goto out; +@@ -1740,12 +1748,13 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, + struct extent_buffer *eb, int slot, + struct btrfs_key *key) + { +- int ret; ++ int ret = 0; + u32 item_size = btrfs_item_size_nr(eb, slot); + struct btrfs_dir_item *di; + int name_len; + unsigned long ptr; + unsigned long ptr_end; ++ struct btrfs_path *fixup_path = NULL; + + ptr = btrfs_item_ptr_offset(eb, slot); + ptr_end = ptr + item_size; +@@ -1755,12 +1764,59 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, + return -EIO; + name_len = btrfs_dir_name_len(eb, di); + ret = replay_one_name(trans, root, path, eb, di, key); +- if (ret) +- return ret; ++ if (ret < 0) ++ break; + ptr = (unsigned long)(di + 1); + ptr += name_len; ++ ++ /* ++ * If this entry refers to a non-directory (directories can not ++ * have a link count > 1) and it was added in the transaction ++ * that was not committed, make sure we fixup the link count of ++ * the inode it the entry points to. Otherwise something like ++ * the following would result in a directory pointing to an ++ * inode with a wrong link that does not account for this dir ++ * entry: ++ * ++ * mkdir testdir ++ * touch testdir/foo ++ * touch testdir/bar ++ * sync ++ * ++ * ln testdir/bar testdir/bar_link ++ * ln testdir/foo testdir/foo_link ++ * xfs_io -c "fsync" testdir/bar ++ * ++ * <power failure> ++ * ++ * mount fs, log replay happens ++ * ++ * File foo would remain with a link count of 1 when it has two ++ * entries pointing to it in the directory testdir. This would ++ * make it impossible to ever delete the parent directory has ++ * it would result in stale dentries that can never be deleted. ++ */ ++ if (ret == 1 && btrfs_dir_type(eb, di) != BTRFS_FT_DIR) { ++ struct btrfs_key di_key; ++ ++ if (!fixup_path) { ++ fixup_path = btrfs_alloc_path(); ++ if (!fixup_path) { ++ ret = -ENOMEM; ++ break; ++ } ++ } ++ ++ btrfs_dir_item_key_to_cpu(eb, di, &di_key); ++ ret = link_to_fixup_dir(trans, root, fixup_path, ++ di_key.objectid); ++ if (ret) ++ break; ++ } ++ ret = 0; + } +- return 0; ++ btrfs_free_path(fixup_path); ++ return ret; + } + + /* + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch new/patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch --- old/patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch 1970-01-01 01:00:00.000000000 +0100 +++ new/patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch 2015-08-28 12:59:34.000000000 +0200 @@ -0,0 +1,218 @@ +From: Haibo Chen <haibo.chen@freescale.com> +Date: Tue, 25 Aug 2015 10:02:11 +0800 +Subject: mmc: sdhci: fix dma memory leak in sdhci_pre_req() +Patch-mainline: Queued in subsystem maintainer repository +Git-commit: d31911b9374a76560d2c8ea4aa6ce5781621e81d +Git-repo: git://git.linaro.org/people/ulf.hansson/mmc.git#next +References: bnc#934531 + +Currently one mrq->data maybe execute dma_map_sg() twice +when mmc subsystem prepare over one new request, and the +following log show up: + sdhci[sdhci_pre_dma_transfer] invalid cookie: 24, next-cookie 25 + +In this condition, mrq->date map a dma-memory(1) in sdhci_pre_req +for the first time, and map another dma-memory(2) in sdhci_prepare_data +for the second time. But driver only unmap the dma-memory(2), and +dma-memory(1) never unmapped, which cause the dma memory leak issue. + +This patch use another method to map the dma memory for the mrq->data +which can fix this dma memory leak issue. + +[js] add sg_count to mmc_data as happenned in 208489032bdd8d (mmc: + mediatek: Add Mediatek MMC driver). + +Fixes: 348487cb28e6 ("mmc: sdhci: use pipeline mmc requests to improve performance") +Reported-and-tested-by: Jiri Slaby <jslaby@suse.cz> +Signed-off-by: Haibo Chen <haibo.chen@freescale.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +Signed-off-by: Jiri Slaby <jslaby@suse.cz> +--- + drivers/mmc/host/sdhci.c | 67 +++++++++++++++++------------------------------ + drivers/mmc/host/sdhci.h | 8 ++--- + include/linux/mmc/core.h | 1 + 3 files changed, 30 insertions(+), 46 deletions(-) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -55,8 +55,7 @@ static int sdhci_execute_tuning(struct m + static void sdhci_tuning_timer(unsigned long data); + static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); + static int sdhci_pre_dma_transfer(struct sdhci_host *host, +- struct mmc_data *data, +- struct sdhci_host_next *next); ++ struct mmc_data *data); + static int sdhci_do_get_cd(struct sdhci_host *host); + + #ifdef CONFIG_PM +@@ -510,7 +509,7 @@ static int sdhci_adma_table_pre(struct s + goto fail; + BUG_ON(host->align_addr & host->align_mask); + +- host->sg_count = sdhci_pre_dma_transfer(host, data, NULL); ++ host->sg_count = sdhci_pre_dma_transfer(host, data); + if (host->sg_count < 0) + goto unmap_align; + +@@ -649,9 +648,11 @@ static void sdhci_adma_table_post(struct + } + } + +- if (!data->host_cookie) ++ if (data->host_cookie == COOKIE_MAPPED) { + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, direction); ++ data->host_cookie = COOKIE_UNMAPPED; ++ } + } + + static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) +@@ -847,7 +848,7 @@ static void sdhci_prepare_data(struct sd + } else { + int sg_cnt; + +- sg_cnt = sdhci_pre_dma_transfer(host, data, NULL); ++ sg_cnt = sdhci_pre_dma_transfer(host, data); + if (sg_cnt <= 0) { + /* + * This only happens when someone fed +@@ -963,11 +964,13 @@ static void sdhci_finish_data(struct sdh + if (host->flags & SDHCI_USE_ADMA) + sdhci_adma_table_post(host, data); + else { +- if (!data->host_cookie) ++ if (data->host_cookie == COOKIE_MAPPED) { + dma_unmap_sg(mmc_dev(host->mmc), + data->sg, data->sg_len, + (data->flags & MMC_DATA_READ) ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); ++ data->host_cookie = COOKIE_UNMAPPED; ++ } + } + } + +@@ -2129,49 +2132,36 @@ static void sdhci_post_req(struct mmc_ho + struct mmc_data *data = mrq->data; + + if (host->flags & SDHCI_REQ_USE_DMA) { +- if (data->host_cookie) ++ if (data->host_cookie == COOKIE_GIVEN || ++ data->host_cookie == COOKIE_MAPPED) + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + data->flags & MMC_DATA_WRITE ? + DMA_TO_DEVICE : DMA_FROM_DEVICE); +- mrq->data->host_cookie = 0; ++ data->host_cookie = COOKIE_UNMAPPED; + } + } + + static int sdhci_pre_dma_transfer(struct sdhci_host *host, +- struct mmc_data *data, +- struct sdhci_host_next *next) ++ struct mmc_data *data) + { + int sg_count; + +- if (!next && data->host_cookie && +- data->host_cookie != host->next_data.cookie) { +- pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n", +- __func__, data->host_cookie, host->next_data.cookie); +- data->host_cookie = 0; ++ if (data->host_cookie == COOKIE_MAPPED) { ++ data->host_cookie = COOKIE_GIVEN; ++ return data->sg_count; + } + +- /* Check if next job is already prepared */ +- if (next || +- (!next && data->host_cookie != host->next_data.cookie)) { +- sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, +- data->sg_len, +- data->flags & MMC_DATA_WRITE ? +- DMA_TO_DEVICE : DMA_FROM_DEVICE); +- +- } else { +- sg_count = host->next_data.sg_count; +- host->next_data.sg_count = 0; +- } ++ WARN_ON(data->host_cookie == COOKIE_GIVEN); + ++ sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ data->flags & MMC_DATA_WRITE ? ++ DMA_TO_DEVICE : DMA_FROM_DEVICE); + + if (sg_count == 0) +- return -EINVAL; ++ return -ENOSPC; + +- if (next) { +- next->sg_count = sg_count; +- data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie; +- } else +- host->sg_count = sg_count; ++ data->sg_count = sg_count; ++ data->host_cookie = COOKIE_MAPPED; + + return sg_count; + } +@@ -2181,16 +2171,10 @@ static void sdhci_pre_req(struct mmc_hos + { + struct sdhci_host *host = mmc_priv(mmc); + +- if (mrq->data->host_cookie) { +- mrq->data->host_cookie = 0; +- return; +- } ++ mrq->data->host_cookie = COOKIE_UNMAPPED; + + if (host->flags & SDHCI_REQ_USE_DMA) +- if (sdhci_pre_dma_transfer(host, +- mrq->data, +- &host->next_data) < 0) +- mrq->data->host_cookie = 0; ++ sdhci_pre_dma_transfer(host, mrq->data); + } + + static void sdhci_card_event(struct mmc_host *mmc) +@@ -3088,7 +3072,6 @@ int sdhci_add_host(struct sdhci_host *ho + host->max_clk = host->ops->get_max_clock(host); + } + +- host->next_data.cookie = 1; + /* + * In case of Host Controller v3.00, find out whether clock + * multiplier is supported. +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -309,9 +309,10 @@ struct sdhci_adma2_64_desc { + */ + #define SDHCI_MAX_SEGS 128 + +-struct sdhci_host_next { +- unsigned int sg_count; +- s32 cookie; ++enum sdhci_cookie { ++ COOKIE_UNMAPPED, ++ COOKIE_MAPPED, ++ COOKIE_GIVEN, + }; + + struct sdhci_host { +@@ -506,7 +507,6 @@ struct sdhci_host { + #define SDHCI_TUNING_MODE_1 0 + struct timer_list tuning_timer; /* Timer for tuning */ + +- struct sdhci_host_next next_data; + unsigned long private[0] ____cacheline_aligned; + }; + +--- a/include/linux/mmc/core.h ++++ b/include/linux/mmc/core.h +@@ -121,6 +121,7 @@ struct mmc_data { + struct mmc_request *mrq; /* associated request */ + + unsigned int sg_len; /* size of scatter list */ ++ int sg_count; /* mapped sg entries */ + struct scatterlist *sg; /* I/O scatter list */ + s32 host_cookie; /* host private data */ + }; ++++++ patches.suse.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/patches.suse/0001-Revert-mmc-sdhci-fix-low-memory-corruption.patch new/patches.suse/0001-Revert-mmc-sdhci-fix-low-memory-corruption.patch --- old/patches.suse/0001-Revert-mmc-sdhci-fix-low-memory-corruption.patch 2015-08-03 20:25:03.000000000 +0200 +++ new/patches.suse/0001-Revert-mmc-sdhci-fix-low-memory-corruption.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,28 +0,0 @@ -From 248505da0f98c823b626aac1160b3cdc8e54e10c Mon Sep 17 00:00:00 2001 -From: Jiri Slaby <jslaby@suse.cz> -Date: Tue, 28 Jul 2015 15:54:25 +0200 -Subject: [PATCH 1/2] Revert "mmc: sdhci: fix low memory corruption" -Patch-mainline: no -References: bnc#934531 - -This reverts commit 62a7f368ffbc13d9aedfdd7aeae711b177db69ac. ---- - drivers/mmc/host/sdhci.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index 9231cdfe2757..c80287a02735 100644 ---- a/drivers/mmc/host/sdhci.c -+++ b/drivers/mmc/host/sdhci.c -@@ -848,7 +848,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) - int sg_cnt; - - sg_cnt = sdhci_pre_dma_transfer(host, data, NULL); -- if (sg_cnt <= 0) { -+ if (sg_cnt == 0) { - /* - * This only happens when someone fed - * us an invalid request. --- -2.1.4 - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/patches.suse/0002-Revert-mmc-sdhci-use-pipeline-mmc-requests-to-improv.patch new/patches.suse/0002-Revert-mmc-sdhci-use-pipeline-mmc-requests-to-improv.patch --- old/patches.suse/0002-Revert-mmc-sdhci-use-pipeline-mmc-requests-to-improv.patch 2015-08-03 20:25:03.000000000 +0200 +++ new/patches.suse/0002-Revert-mmc-sdhci-use-pipeline-mmc-requests-to-improv.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,204 +0,0 @@ -From 019207a490b5992a51888ebabc419af7749f0bae Mon Sep 17 00:00:00 2001 -From: Jiri Slaby <jslaby@suse.cz> -Date: Tue, 28 Jul 2015 15:56:07 +0200 -Subject: [PATCH 2/2] Revert "mmc: sdhci: use pipeline mmc requests to improve - performance" -Patch-mainline: no -References: bnc#934531 - -This reverts commit 348487cb28e66b032bae1b38424d81bf5b444408. - -Conflicts: - drivers/mmc/host/sdhci.c - include/linux/mmc/sdhci.h ---- - drivers/mmc/host/sdhci.c | 99 ++++++------------------------------------------ - drivers/mmc/host/sdhci.h | 6 --- - 2 files changed, 12 insertions(+), 93 deletions(-) - -diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index c80287a02735..8b5e37415949 100644 ---- a/drivers/mmc/host/sdhci.c -+++ b/drivers/mmc/host/sdhci.c -@@ -54,9 +54,6 @@ static void sdhci_finish_command(struct sdhci_host *); - static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); - static void sdhci_tuning_timer(unsigned long data); - static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); --static int sdhci_pre_dma_transfer(struct sdhci_host *host, -- struct mmc_data *data, -- struct sdhci_host_next *next); - static int sdhci_do_get_cd(struct sdhci_host *host); - - #ifdef CONFIG_PM -@@ -510,8 +507,9 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, - goto fail; - BUG_ON(host->align_addr & host->align_mask); - -- host->sg_count = sdhci_pre_dma_transfer(host, data, NULL); -- if (host->sg_count < 0) -+ host->sg_count = dma_map_sg(mmc_dev(host->mmc), -+ data->sg, data->sg_len, direction); -+ if (host->sg_count == 0) - goto unmap_align; - - desc = host->adma_table; -@@ -649,9 +647,8 @@ static void sdhci_adma_table_post(struct sdhci_host *host, - } - } - -- if (!data->host_cookie) -- dma_unmap_sg(mmc_dev(host->mmc), data->sg, -- data->sg_len, direction); -+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, -+ data->sg_len, direction); - } - - static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) -@@ -847,7 +844,11 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) - } else { - int sg_cnt; - -- sg_cnt = sdhci_pre_dma_transfer(host, data, NULL); -+ sg_cnt = dma_map_sg(mmc_dev(host->mmc), -+ data->sg, data->sg_len, -+ (data->flags & MMC_DATA_READ) ? -+ DMA_FROM_DEVICE : -+ DMA_TO_DEVICE); - if (sg_cnt == 0) { - /* - * This only happens when someone fed -@@ -963,10 +964,8 @@ static void sdhci_finish_data(struct sdhci_host *host) - if (host->flags & SDHCI_USE_ADMA) - sdhci_adma_table_post(host, data); - else { -- if (!data->host_cookie) -- dma_unmap_sg(mmc_dev(host->mmc), -- data->sg, data->sg_len, -- (data->flags & MMC_DATA_READ) ? -+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, -+ data->sg_len, (data->flags & MMC_DATA_READ) ? - DMA_FROM_DEVICE : DMA_TO_DEVICE); - } - } -@@ -2122,77 +2121,6 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) - } - } - --static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, -- int err) --{ -- struct sdhci_host *host = mmc_priv(mmc); -- struct mmc_data *data = mrq->data; -- -- if (host->flags & SDHCI_REQ_USE_DMA) { -- if (data->host_cookie) -- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -- data->flags & MMC_DATA_WRITE ? -- DMA_TO_DEVICE : DMA_FROM_DEVICE); -- mrq->data->host_cookie = 0; -- } --} -- --static int sdhci_pre_dma_transfer(struct sdhci_host *host, -- struct mmc_data *data, -- struct sdhci_host_next *next) --{ -- int sg_count; -- -- if (!next && data->host_cookie && -- data->host_cookie != host->next_data.cookie) { -- pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n", -- __func__, data->host_cookie, host->next_data.cookie); -- data->host_cookie = 0; -- } -- -- /* Check if next job is already prepared */ -- if (next || -- (!next && data->host_cookie != host->next_data.cookie)) { -- sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, -- data->sg_len, -- data->flags & MMC_DATA_WRITE ? -- DMA_TO_DEVICE : DMA_FROM_DEVICE); -- -- } else { -- sg_count = host->next_data.sg_count; -- host->next_data.sg_count = 0; -- } -- -- -- if (sg_count == 0) -- return -EINVAL; -- -- if (next) { -- next->sg_count = sg_count; -- data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie; -- } else -- host->sg_count = sg_count; -- -- return sg_count; --} -- --static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, -- bool is_first_req) --{ -- struct sdhci_host *host = mmc_priv(mmc); -- -- if (mrq->data->host_cookie) { -- mrq->data->host_cookie = 0; -- return; -- } -- -- if (host->flags & SDHCI_REQ_USE_DMA) -- if (sdhci_pre_dma_transfer(host, -- mrq->data, -- &host->next_data) < 0) -- mrq->data->host_cookie = 0; --} -- - static void sdhci_card_event(struct mmc_host *mmc) - { - struct sdhci_host *host = mmc_priv(mmc); -@@ -2226,8 +2154,6 @@ static void sdhci_card_event(struct mmc_host *mmc) - - static const struct mmc_host_ops sdhci_ops = { - .request = sdhci_request, -- .post_req = sdhci_post_req, -- .pre_req = sdhci_pre_req, - .set_ios = sdhci_set_ios, - .get_cd = sdhci_get_cd, - .get_ro = sdhci_get_ro, -@@ -3085,7 +3011,6 @@ int sdhci_add_host(struct sdhci_host *host) - host->max_clk = host->ops->get_max_clock(host); - } - -- host->next_data.cookie = 1; - /* - * In case of Host Controller v3.00, find out whether clock - * multiplier is supported. -diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h -index e639b7f435e5..b29e638cc81b 100644 ---- a/drivers/mmc/host/sdhci.h -+++ b/drivers/mmc/host/sdhci.h -@@ -309,11 +309,6 @@ struct sdhci_adma2_64_desc { - */ - #define SDHCI_MAX_SEGS 128 - --struct sdhci_host_next { -- unsigned int sg_count; -- s32 cookie; --}; -- - struct sdhci_host { - /* Data set by hardware interface driver */ - const char *hw_name; /* Hardware bus name */ -@@ -506,7 +501,6 @@ struct sdhci_host { - #define SDHCI_TUNING_MODE_1 0 - struct timer_list tuning_timer; /* Timer for tuning */ - -- struct sdhci_host_next next_data; - unsigned long private[0] ____cacheline_aligned; - }; - --- -2.1.4 - ++++++ series.conf ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:11.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:11.000000000 +0200 @@ -265,6 +265,8 @@ ######################################################## patches.suse/btrfs-use-correct-device-for-maps.patch patches.suse/btrfs-fix-hang-during-inode-eviction-due-to-concurre.patch + patches.fixes/btrfs-fix-stale-directory-entries-after-fsync-log-replay + patches.fixes/btrfs-fix-stale-dir-entries-after-unlink-inode-eviction-and-fsync ######################################################## # Reiserfs Patches @@ -411,8 +413,7 @@ # Needs updating WRT d27769ec (block: add GENHD_FL_NO_PART_SCAN) +hare patches.suse/no-partition-scan - patches.suse/0001-Revert-mmc-sdhci-fix-low-memory-corruption.patch - patches.suse/0002-Revert-mmc-sdhci-use-pipeline-mmc-requests-to-improv.patch + patches.fixes/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch ######################################################## # Other drivers we have added to the tree ++++++ source-timestamp ++++++ --- /var/tmp/diff_new_pack.Djchip/_old 2015-09-02 00:35:11.000000000 +0200 +++ /var/tmp/diff_new_pack.Djchip/_new 2015-09-02 00:35:11.000000000 +0200 @@ -1,3 +1,3 @@ -2015-08-20 16:57:58 +0200 -GIT Revision: ce0123d378a911d518daedaf63cc4514d5d16e6b +2015-08-28 12:59:34 +0200 +GIT Revision: d867e863d55239553067c5f9ac7ecdd96076bd9f GIT Branch: stable
participants (1)
-
root@hilbert.suse.de