summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2014-10-17 07:46:58 -0400
committerMike Pagano <mpagano@gentoo.org>2014-10-17 07:46:58 -0400
commitf5b0f4e7ada52dcbc0815296376406083b23b7bf (patch)
treedece981a48199eb16423b576d86992c2c497bc5c
parentPrevent a leak of unreachable mounts. See bug #524848 (diff)
downloadlinux-patches-f5b0f4e7ada52dcbc0815296376406083b23b7bf.tar.gz
linux-patches-f5b0f4e7ada52dcbc0815296376406083b23b7bf.tar.bz2
linux-patches-f5b0f4e7ada52dcbc0815296376406083b23b7bf.zip
Fix loading of special inodes. See bug #5254763.17-3
-rw-r--r--0000_README4
-rw-r--r--1900_udf-Fix-loading-of-special-inodes.patch147
2 files changed, 151 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 8ed607e8..8e902b15 100644
--- a/0000_README
+++ b/0000_README
@@ -55,6 +55,10 @@ Patch: 1510_mnt-Prevent-pivot_root-from-creating-a-loop-in-the-m.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=524848
Desc: Prevent a leak of unreachable mounts
+Patch: 1900_udf-Fix-loading-of-special-inodes.patch
+From: https://bugs.gentoo.org/show_bug.cgi?id=525476
+Desc: Fix loading of special inodes
+
Patch: 2400_kcopy-patch-for-infiniband-driver.patch
From: Alexey Shvetsov <alexxy@gentoo.org>
Desc: Zero copy for infiniband psm userspace driver
diff --git a/1900_udf-Fix-loading-of-special-inodes.patch b/1900_udf-Fix-loading-of-special-inodes.patch
new file mode 100644
index 00000000..c0ef46ca
--- /dev/null
+++ b/1900_udf-Fix-loading-of-special-inodes.patch
@@ -0,0 +1,147 @@
+From 6174c2eb8ecef271159bdcde460ce8af54d8f72f Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 9 Oct 2014 12:52:16 +0200
+Subject: [PATCH] udf: Fix loading of special inodes
+Cc: mpagano@gentoo.org
+
+Some UDF media have special inodes (like VAT or metadata partition
+inodes) whose link_count is 0. Thus commit 4071b9136223 (udf: Properly
+detect stale inodes) broke loading these inodes because udf_iget()
+started returning -ESTALE for them. Since we still need to properly
+detect stale inodes queried by NFS, create two variants of udf_iget() -
+one which is used for looking up special inodes (which ignores
+link_count == 0) and one which is used for other cases which return
+ESTALE when link_count == 0.
+
+Fixes: 4071b913622316970d0e1919f7d82b4403fec5f2
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Mike Pagano <mpagano@gentoo.org>
+---
+ fs/udf/inode.c | 14 +++++++++-----
+ fs/udf/super.c | 10 +++++-----
+ fs/udf/udfdecl.h | 13 ++++++++++++-
+ 3 files changed, 26 insertions(+), 11 deletions(-)
+
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 0859884..c9b4df5 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -1277,7 +1277,7 @@ update_time:
+ */
+ #define UDF_MAX_ICB_NESTING 1024
+
+-static int udf_read_inode(struct inode *inode)
++static int udf_read_inode(struct inode *inode, bool hidden_inode)
+ {
+ struct buffer_head *bh = NULL;
+ struct fileEntry *fe;
+@@ -1436,8 +1436,11 @@ reread:
+
+ link_count = le16_to_cpu(fe->fileLinkCount);
+ if (!link_count) {
+- ret = -ESTALE;
+- goto out;
++ if (!hidden_inode) {
++ ret = -ESTALE;
++ goto out;
++ }
++ link_count = 1;
+ }
+ set_nlink(inode, link_count);
+
+@@ -1826,7 +1829,8 @@ out:
+ return err;
+ }
+
+-struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
++struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
++ bool hidden_inode)
+ {
+ unsigned long block = udf_get_lb_pblock(sb, ino, 0);
+ struct inode *inode = iget_locked(sb, block);
+@@ -1839,7 +1843,7 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
+ return inode;
+
+ memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
+- err = udf_read_inode(inode);
++ err = udf_read_inode(inode, hidden_inode);
+ if (err < 0) {
+ iget_failed(inode);
+ return ERR_PTR(err);
+diff --git a/fs/udf/super.c b/fs/udf/super.c
+index 5401fc3..e229315 100644
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -959,7 +959,7 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
+ addr.logicalBlockNum = meta_file_loc;
+ addr.partitionReferenceNum = partition_num;
+
+- metadata_fe = udf_iget(sb, &addr);
++ metadata_fe = udf_iget_special(sb, &addr);
+
+ if (IS_ERR(metadata_fe)) {
+ udf_warn(sb, "metadata inode efe not found\n");
+@@ -1020,7 +1020,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
+ udf_debug("Bitmap file location: block = %d part = %d\n",
+ addr.logicalBlockNum, addr.partitionReferenceNum);
+
+- fe = udf_iget(sb, &addr);
++ fe = udf_iget_special(sb, &addr);
+ if (IS_ERR(fe)) {
+ if (sb->s_flags & MS_RDONLY)
+ udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");
+@@ -1119,7 +1119,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
+ };
+ struct inode *inode;
+
+- inode = udf_iget(sb, &loc);
++ inode = udf_iget_special(sb, &loc);
+ if (IS_ERR(inode)) {
+ udf_debug("cannot load unallocSpaceTable (part %d)\n",
+ p_index);
+@@ -1154,7 +1154,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
+ };
+ struct inode *inode;
+
+- inode = udf_iget(sb, &loc);
++ inode = udf_iget_special(sb, &loc);
+ if (IS_ERR(inode)) {
+ udf_debug("cannot load freedSpaceTable (part %d)\n",
+ p_index);
+@@ -1198,7 +1198,7 @@ static void udf_find_vat_block(struct super_block *sb, int p_index,
+ vat_block >= map->s_partition_root &&
+ vat_block >= start_block - 3; vat_block--) {
+ ino.logicalBlockNum = vat_block - map->s_partition_root;
+- inode = udf_iget(sb, &ino);
++ inode = udf_iget_special(sb, &ino);
+ if (!IS_ERR(inode)) {
+ sbi->s_vat_inode = inode;
+ break;
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index 742557b..1cc3c99 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -138,7 +138,18 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
+ /* file.c */
+ extern long udf_ioctl(struct file *, unsigned int, unsigned long);
+ /* inode.c */
+-extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);
++extern struct inode *__udf_iget(struct super_block *, struct kernel_lb_addr *,
++ bool hidden_inode);
++static inline struct inode *udf_iget_special(struct super_block *sb,
++ struct kernel_lb_addr *ino)
++{
++ return __udf_iget(sb, ino, true);
++}
++static inline struct inode *udf_iget(struct super_block *sb,
++ struct kernel_lb_addr *ino)
++{
++ return __udf_iget(sb, ino, false);
++}
+ extern int udf_expand_file_adinicb(struct inode *);
+ extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
+ extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
+--
+2.1.1
+