Skip to content

Commit

Permalink
udf: Make udf_read_inode() and udf_iget() return error
Browse files Browse the repository at this point in the history
Currently __udf_read_inode() wasn't returning anything and we found out
whether we succeeded reading inode by checking whether inode is bad or
not. udf_iget() returned NULL on failure and inode pointer otherwise.
Make these two functions properly propagate errors up the call stack and
use the return value in callers.

Signed-off-by: Jan Kara <[email protected]>
  • Loading branch information
jankara committed Sep 4, 2014
1 parent c03aa9f commit 6d3d5e8
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 95 deletions.
99 changes: 46 additions & 53 deletions fs/udf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1277,18 +1277,27 @@ int udf_setsize(struct inode *inode, loff_t newsize)
*/
#define UDF_MAX_ICB_NESTING 1024

static void __udf_read_inode(struct inode *inode)
static int udf_read_inode(struct inode *inode)
{
struct buffer_head *bh = NULL;
struct fileEntry *fe;
struct extendedFileEntry *efe;
uint16_t ident;
struct udf_inode_info *iinfo = UDF_I(inode);
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
struct kernel_lb_addr *iloc = &iinfo->i_location;
unsigned int link_count;
unsigned int indirections = 0;
int ret = -EIO;

reread:
if (iloc->logicalBlockNum >=
sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) {
udf_debug("block=%d, partition=%d out of range\n",
iloc->logicalBlockNum, iloc->partitionReferenceNum);
return -EIO;
}

/*
* Set defaults, but the inode is still incomplete!
* Note: get_new_inode() sets the following on a new inode:
Expand All @@ -1301,20 +1310,17 @@ static void __udf_read_inode(struct inode *inode)
* i_nlink = 1
* i_op = NULL;
*/
bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident);
bh = udf_read_ptagged(inode->i_sb, iloc, 0, &ident);
if (!bh) {
udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino);
make_bad_inode(inode);
return;
return -EIO;
}

if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
ident != TAG_IDENT_USE) {
udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n",
inode->i_ino, ident);
brelse(bh);
make_bad_inode(inode);
return;
goto out;
}

fe = (struct fileEntry *)bh->b_data;
Expand All @@ -1323,8 +1329,7 @@ static void __udf_read_inode(struct inode *inode)
if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
struct buffer_head *ibh;

ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1,
&ident);
ibh = udf_read_ptagged(inode->i_sb, iloc, 1, &ident);
if (ident == TAG_IDENT_IE && ibh) {
struct kernel_lb_addr loc;
struct indirectEntry *ie;
Expand All @@ -1333,7 +1338,6 @@ static void __udf_read_inode(struct inode *inode)
loc = lelb_to_cpu(ie->indirectICB.extLocation);

if (ie->indirectICB.extLength) {
brelse(bh);
brelse(ibh);
memcpy(&iinfo->i_location, &loc,
sizeof(struct kernel_lb_addr));
Expand All @@ -1342,19 +1346,17 @@ static void __udf_read_inode(struct inode *inode)
"too many ICBs in ICB hierarchy"
" (max %d supported)\n",
UDF_MAX_ICB_NESTING);
make_bad_inode(inode);
return;
goto out;
}
brelse(bh);
goto reread;
}
}
brelse(ibh);
} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
udf_err(inode->i_sb, "unsupported strategy type: %d\n",
le16_to_cpu(fe->icbTag.strategyType));
brelse(bh);
make_bad_inode(inode);
return;
goto out;
}
if (fe->icbTag.strategyType == cpu_to_le16(4))
iinfo->i_strat4096 = 0;
Expand All @@ -1372,23 +1374,21 @@ static void __udf_read_inode(struct inode *inode)
if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
iinfo->i_efe = 1;
iinfo->i_use = 0;
if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct extendedFileEntry))) {
make_bad_inode(inode);
return;
}
ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct extendedFileEntry));
if (ret)
goto out;
memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct extendedFileEntry),
inode->i_sb->s_blocksize -
sizeof(struct extendedFileEntry));
} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
iinfo->i_efe = 0;
iinfo->i_use = 0;
if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct fileEntry))) {
make_bad_inode(inode);
return;
}
ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct fileEntry));
if (ret)
goto out;
memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct fileEntry),
inode->i_sb->s_blocksize - sizeof(struct fileEntry));
Expand All @@ -1398,18 +1398,18 @@ static void __udf_read_inode(struct inode *inode)
iinfo->i_lenAlloc = le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->
lengthAllocDescs);
if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry))) {
make_bad_inode(inode);
return;
}
ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry));
if (ret)
goto out;
memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct unallocSpaceEntry),
inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry));
return;
return 0;
}

ret = -EIO;
read_lock(&sbi->s_cred_lock);
i_uid_write(inode, le32_to_cpu(fe->uid));
if (!uid_valid(inode->i_uid) ||
Expand Down Expand Up @@ -1531,8 +1531,7 @@ static void __udf_read_inode(struct inode *inode)
default:
udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n",
inode->i_ino, fe->icbTag.fileType);
make_bad_inode(inode);
return;
goto out;
}
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
struct deviceSpec *dsea =
Expand All @@ -1543,9 +1542,12 @@ static void __udf_read_inode(struct inode *inode)
le32_to_cpu(dsea->minorDeviceIdent)));
/* Developer ID ??? */
} else
make_bad_inode(inode);
goto out;
}
ret = 0;
out:
brelse(bh);
return ret;
}

static int udf_alloc_i_data(struct inode *inode, size_t size)
Expand Down Expand Up @@ -1825,32 +1827,23 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
{
unsigned long block = udf_get_lb_pblock(sb, ino, 0);
struct inode *inode = iget_locked(sb, block);
int err;

if (!inode)
return NULL;

if (inode->i_state & I_NEW) {
memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
__udf_read_inode(inode);
unlock_new_inode(inode);
}
return ERR_PTR(-ENOMEM);

if (is_bad_inode(inode))
goto out_iput;
if (!(inode->i_state & I_NEW))
return inode;

if (ino->logicalBlockNum >= UDF_SB(sb)->
s_partmaps[ino->partitionReferenceNum].s_partition_len) {
udf_debug("block=%d, partition=%d out of range\n",
ino->logicalBlockNum, ino->partitionReferenceNum);
make_bad_inode(inode);
goto out_iput;
memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
err = udf_read_inode(inode);
if (err < 0) {
iget_failed(inode);
return ERR_PTR(err);
}
unlock_new_inode(inode);

return inode;

out_iput:
iput(inode);
return NULL;
}

int udf_add_aext(struct inode *inode, struct extent_position *epos,
Expand Down
22 changes: 9 additions & 13 deletions fs/udf/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
NULL, 0),
};
inode = udf_iget(dir->i_sb, lb);
if (!inode) {
return ERR_PTR(-EACCES);
}
if (IS_ERR(inode))
return inode;
} else
#endif /* UDF_RECOVERY */

Expand All @@ -285,9 +284,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,

loc = lelb_to_cpu(cfi.icb.extLocation);
inode = udf_iget(dir->i_sb, &loc);
if (!inode) {
return ERR_PTR(-EACCES);
}
if (IS_ERR(inode))
return ERR_CAST(inode);
}

return d_splice_alias(inode, dentry);
Expand Down Expand Up @@ -1222,20 +1220,18 @@ static struct dentry *udf_get_parent(struct dentry *child)
struct udf_fileident_bh fibh;

if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
goto out_unlock;
return ERR_PTR(-EACCES);

if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh);
brelse(fibh.sbh);

tloc = lelb_to_cpu(cfi.icb.extLocation);
inode = udf_iget(child->d_inode->i_sb, &tloc);
if (!inode)
goto out_unlock;
if (IS_ERR(inode))
return ERR_CAST(inode);

return d_obtain_alias(inode);
out_unlock:
return ERR_PTR(-EACCES);
}


Expand All @@ -1252,8 +1248,8 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
loc.partitionReferenceNum = partref;
inode = udf_iget(sb, &loc);

if (inode == NULL)
return ERR_PTR(-ENOMEM);
if (IS_ERR(inode))
return ERR_CAST(inode);

if (generation && inode->i_generation != generation) {
iput(inode);
Expand Down
Loading

0 comments on commit 6d3d5e8

Please sign in to comment.