aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-10-09 06:52:16 -0400
committerJan Kara <jack@suse.cz>2014-10-09 07:06:14 -0400
commit6174c2eb8ecef271159bdcde460ce8af54d8f72f (patch)
treefc00824fdd8231ac9ee32714fc86493149af29d1 /fs/udf
parentc53f755d339b5546600c316333140d5fe958941d (diff)
udf: Fix loading of special inodes
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>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/inode.c14
-rw-r--r--fs/udf/super.c10
-rw-r--r--fs/udf/udfdecl.h13
3 files changed, 26 insertions, 11 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 08598843288f..c9b4df5810d5 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1277,7 +1277,7 @@ update_time:
1277 */ 1277 */
1278#define UDF_MAX_ICB_NESTING 1024 1278#define UDF_MAX_ICB_NESTING 1024
1279 1279
1280static int udf_read_inode(struct inode *inode) 1280static int udf_read_inode(struct inode *inode, bool hidden_inode)
1281{ 1281{
1282 struct buffer_head *bh = NULL; 1282 struct buffer_head *bh = NULL;
1283 struct fileEntry *fe; 1283 struct fileEntry *fe;
@@ -1436,8 +1436,11 @@ reread:
1436 1436
1437 link_count = le16_to_cpu(fe->fileLinkCount); 1437 link_count = le16_to_cpu(fe->fileLinkCount);
1438 if (!link_count) { 1438 if (!link_count) {
1439 ret = -ESTALE; 1439 if (!hidden_inode) {
1440 goto out; 1440 ret = -ESTALE;
1441 goto out;
1442 }
1443 link_count = 1;
1441 } 1444 }
1442 set_nlink(inode, link_count); 1445 set_nlink(inode, link_count);
1443 1446
@@ -1826,7 +1829,8 @@ out:
1826 return err; 1829 return err;
1827} 1830}
1828 1831
1829struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) 1832struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
1833 bool hidden_inode)
1830{ 1834{
1831 unsigned long block = udf_get_lb_pblock(sb, ino, 0); 1835 unsigned long block = udf_get_lb_pblock(sb, ino, 0);
1832 struct inode *inode = iget_locked(sb, block); 1836 struct inode *inode = iget_locked(sb, block);
@@ -1839,7 +1843,7 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
1839 return inode; 1843 return inode;
1840 1844
1841 memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); 1845 memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
1842 err = udf_read_inode(inode); 1846 err = udf_read_inode(inode, hidden_inode);
1843 if (err < 0) { 1847 if (err < 0) {
1844 iget_failed(inode); 1848 iget_failed(inode);
1845 return ERR_PTR(err); 1849 return ERR_PTR(err);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 5401fc33f5cc..e229315bbf7a 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,
959 addr.logicalBlockNum = meta_file_loc; 959 addr.logicalBlockNum = meta_file_loc;
960 addr.partitionReferenceNum = partition_num; 960 addr.partitionReferenceNum = partition_num;
961 961
962 metadata_fe = udf_iget(sb, &addr); 962 metadata_fe = udf_iget_special(sb, &addr);
963 963
964 if (IS_ERR(metadata_fe)) { 964 if (IS_ERR(metadata_fe)) {
965 udf_warn(sb, "metadata inode efe not found\n"); 965 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)
1020 udf_debug("Bitmap file location: block = %d part = %d\n", 1020 udf_debug("Bitmap file location: block = %d part = %d\n",
1021 addr.logicalBlockNum, addr.partitionReferenceNum); 1021 addr.logicalBlockNum, addr.partitionReferenceNum);
1022 1022
1023 fe = udf_iget(sb, &addr); 1023 fe = udf_iget_special(sb, &addr);
1024 if (IS_ERR(fe)) { 1024 if (IS_ERR(fe)) {
1025 if (sb->s_flags & MS_RDONLY) 1025 if (sb->s_flags & MS_RDONLY)
1026 udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n"); 1026 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,
1119 }; 1119 };
1120 struct inode *inode; 1120 struct inode *inode;
1121 1121
1122 inode = udf_iget(sb, &loc); 1122 inode = udf_iget_special(sb, &loc);
1123 if (IS_ERR(inode)) { 1123 if (IS_ERR(inode)) {
1124 udf_debug("cannot load unallocSpaceTable (part %d)\n", 1124 udf_debug("cannot load unallocSpaceTable (part %d)\n",
1125 p_index); 1125 p_index);
@@ -1154,7 +1154,7 @@ static int udf_fill_partdesc_info(struct super_block *sb,
1154 }; 1154 };
1155 struct inode *inode; 1155 struct inode *inode;
1156 1156
1157 inode = udf_iget(sb, &loc); 1157 inode = udf_iget_special(sb, &loc);
1158 if (IS_ERR(inode)) { 1158 if (IS_ERR(inode)) {
1159 udf_debug("cannot load freedSpaceTable (part %d)\n", 1159 udf_debug("cannot load freedSpaceTable (part %d)\n",
1160 p_index); 1160 p_index);
@@ -1198,7 +1198,7 @@ static void udf_find_vat_block(struct super_block *sb, int p_index,
1198 vat_block >= map->s_partition_root && 1198 vat_block >= map->s_partition_root &&
1199 vat_block >= start_block - 3; vat_block--) { 1199 vat_block >= start_block - 3; vat_block--) {
1200 ino.logicalBlockNum = vat_block - map->s_partition_root; 1200 ino.logicalBlockNum = vat_block - map->s_partition_root;
1201 inode = udf_iget(sb, &ino); 1201 inode = udf_iget_special(sb, &ino);
1202 if (!IS_ERR(inode)) { 1202 if (!IS_ERR(inode)) {
1203 sbi->s_vat_inode = inode; 1203 sbi->s_vat_inode = inode;
1204 break; 1204 break;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 742557be9936..1cc3c993ebd0 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 *,
138/* file.c */ 138/* file.c */
139extern long udf_ioctl(struct file *, unsigned int, unsigned long); 139extern long udf_ioctl(struct file *, unsigned int, unsigned long);
140/* inode.c */ 140/* inode.c */
141extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); 141extern struct inode *__udf_iget(struct super_block *, struct kernel_lb_addr *,
142 bool hidden_inode);
143static inline struct inode *udf_iget_special(struct super_block *sb,
144 struct kernel_lb_addr *ino)
145{
146 return __udf_iget(sb, ino, true);
147}
148static inline struct inode *udf_iget(struct super_block *sb,
149 struct kernel_lb_addr *ino)
150{
151 return __udf_iget(sb, ino, false);
152}
142extern int udf_expand_file_adinicb(struct inode *); 153extern int udf_expand_file_adinicb(struct inode *);
143extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); 154extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
144extern struct buffer_head *udf_bread(struct inode *, int, int, int *); 155extern struct buffer_head *udf_bread(struct inode *, int, int, int *);