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
+

Reply via email to