forked from Minki/linux
udf: Fix loading of special inodes
Some UDF media have special inodes (like VAT or metadata partition inodes) whose link_count is 0. Thus commit4071b91362
(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:4071b91362
CC: stable@vger.kernel.org Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
c53f755d33
commit
6174c2eb8e
@ -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,9 +1436,12 @@ reread:
|
||||
|
||||
link_count = le16_to_cpu(fe->fileLinkCount);
|
||||
if (!link_count) {
|
||||
if (!hidden_inode) {
|
||||
ret = -ESTALE;
|
||||
goto out;
|
||||
}
|
||||
link_count = 1;
|
||||
}
|
||||
set_nlink(inode, link_count);
|
||||
|
||||
inode->i_size = le64_to_cpu(fe->informationLength);
|
||||
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user