aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2018-11-01 17:57:55 +0100
committerHauke Mehrtens <hauke@hauke-m.de>2018-12-15 12:50:06 +0100
commit52a82ce3dd901a1536c7d7d9d963e9c2d761c816 (patch)
tree79020fb59420fcea7bdc4b12272f7251e101fe64 /target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch
parenta272af75cd8c67d265400f96c1e6bb172315c23c (diff)
downloadupstream-52a82ce3dd901a1536c7d7d9d963e9c2d761c816.tar.gz
upstream-52a82ce3dd901a1536c7d7d9d963e9c2d761c816.tar.bz2
upstream-52a82ce3dd901a1536c7d7d9d963e9c2d761c816.zip
kernel: Copy patches from kernel 4.14 to 4.19
This just copies the files from the kernel 4.14 specific folders into the kernel 4.19 specific folder, no changes are done to the files in this commit. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Diffstat (limited to 'target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch')
-rw-r--r--target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch89
1 files changed, 89 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch b/target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch
new file mode 100644
index 0000000000..71e036c920
--- /dev/null
+++ b/target/linux/generic/backport-4.19/500-ubifs-Handle-re-linking-of-inodes-correctly-while-re.patch
@@ -0,0 +1,89 @@
+From: Richard Weinberger <richard@nod.at>
+Date: Wed, 7 Nov 2018 23:04:43 +0100
+Subject: [PATCH] ubifs: Handle re-linking of inodes correctly while recovery
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+UBIFS's recovery code strictly assumes that a deleted inode will never
+come back, therefore it removes all data which belongs to that inode
+as soon it faces an inode with link count 0 in the replay list.
+Before O_TMPFILE this assumption was perfectly fine. With O_TMPFILE
+it can lead to data loss upon a power-cut.
+
+Consider a journal with entries like:
+0: inode X (nlink = 0) /* O_TMPFILE was created */
+1: data for inode X /* Someone writes to the temp file */
+2: inode X (nlink = 0) /* inode was changed, xattr, chmod, … */
+3: inode X (nlink = 1) /* inode was re-linked via linkat() */
+
+Upon replay of entry #2 UBIFS will drop all data that belongs to inode X,
+this will lead to an empty file after mounting.
+
+As solution for this problem, scan the replay list for a re-link entry
+before dropping data.
+
+Fixes: 474b93704f32 ("ubifs: Implement O_TMPFILE")
+Cc: stable@vger.kernel.org
+Cc: Russell Senior <russell@personaltelco.net>
+Cc: Rafał Miłecki <zajec5@gmail.com>
+Reported-by: Russell Senior <russell@personaltelco.net>
+Reported-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+---
+ fs/ubifs/replay.c | 37 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+--- a/fs/ubifs/replay.c
++++ b/fs/ubifs/replay.c
+@@ -210,6 +210,38 @@ static int trun_remove_range(struct ubif
+ }
+
+ /**
++ * inode_still_linked - check whether inode in question will be re-linked.
++ * @c: UBIFS file-system description object
++ * @rino: replay entry to test
++ *
++ * O_TMPFILE files can be re-linked, this means link count goes from 0 to 1.
++ * This case needs special care, otherwise all references to the inode will
++ * be removed upon the first replay entry of an inode with link count 0
++ * is found.
++ */
++static bool inode_still_linked(struct ubifs_info *c, struct replay_entry *rino)
++{
++ struct replay_entry *r;
++
++ ubifs_assert(rino->deletion);
++ ubifs_assert(key_type(c, &rino->key) == UBIFS_INO_KEY);
++
++ /*
++ * Find the most recent entry for the inode behind @rino and check
++ * whether it is a deletion.
++ */
++ list_for_each_entry_reverse(r, &c->replay_list, list) {
++ ubifs_assert(r->sqnum >= rino->sqnum);
++ if (key_inum(c, &r->key) == key_inum(c, &rino->key))
++ return r->deletion == 0;
++
++ }
++
++ ubifs_assert(0);
++ return false;
++}
++
++/**
+ * apply_replay_entry - apply a replay entry to the TNC.
+ * @c: UBIFS file-system description object
+ * @r: replay entry to apply
+@@ -239,6 +271,11 @@ static int apply_replay_entry(struct ubi
+ {
+ ino_t inum = key_inum(c, &r->key);
+
++ if (inode_still_linked(c, r)) {
++ err = 0;
++ break;
++ }
++
+ err = ubifs_tnc_remove_ino(c, inum);
+ break;
+ }