commit: f5b0f4e7ada52dcbc0815296376406083b23b7bf Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Fri Oct 17 11:46:58 2014 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Fri Oct 17 11:46:58 2014 +0000 URL: http://sources.gentoo.org/gitweb/?p=proj/linux-patches.git;a=commit;h=f5b0f4e7
Fix loading of special inodes. See bug #525476 --- 0000_README | 4 + 1900_udf-Fix-loading-of-special-inodes.patch | 147 +++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) diff --git a/0000_README b/0000_README index 8ed607e..8e902b1 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 <ale...@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 0000000..c0ef46c --- /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 <j...@suse.cz> +Date: Thu, 9 Oct 2014 12:52:16 +0200 +Subject: [PATCH] udf: Fix loading of special inodes +Cc: mpag...@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: sta...@vger.kernel.org +Signed-off-by: Jan Kara <j...@suse.cz> +Signed-off-by: Mike Pagano <mpag...@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 +